From ba6413e1d8aeda582183f2ecbb64f0557324de8d Mon Sep 17 00:00:00 2001 From: Guillaume Claret Date: Fri, 14 Jun 2024 15:54:09 +0200 Subject: [PATCH 1/2] doc: add generated revm verif files --- docs/revm-python-spec/import_revm.py | 121 + .../revm-verif/revm-coq/links/dependencies.md | 51 + .../revm-coq/links/interpreter/interpreter.md | 103 + .../links/interpreter/interpreter/contract.md | 59 + .../interpreter/interpreter/function_stack.md | 71 + .../links/interpreter/interpreter/gas.md | 310 + .../interpreter/instruction_result.md | 151 + .../interpreter/interpreter/shared_memory.md | 54 + .../links/interpreter/interpreter/stack.md | 34 + .../links/interpreter/interpreter_action.md | 93 + .../interpreter_action/call_inputs.md | 159 + .../interpreter_action/create_inputs.md | 53 + .../interpreter_action/eof_create_inputs.md | 58 + .../revm-coq/links/primitives/bytecode.md | 33 + .../revm-coq/links/primitives/bytecode/eof.md | 49 + .../links/primitives/bytecode/eof/body.md | 52 + .../links/primitives/bytecode/eof/header.md | 59 + .../primitives/bytecode/eof/type_section.md | 47 + .../revm-coq/links/primitives/env.md | 41 + .../interpreter/instructions/macros.md | 45 + .../simulations/interpreter/interpreter.md | 28 + .../interpreter/interpreter/gas.md | 41 + .../interpreter/interpreter/stack.md | 124 + .../interpreter/function_stack.md | 700 + .../revm-coq/translations/interpreter/gas.md | 814 + .../translations/interpreter/gas/calc.md | 3455 +++ .../translations/interpreter/gas/constants.md | 127 + .../revm-coq/translations/interpreter/host.md | 1024 + .../translations/interpreter/host/dummy.md | 1238 + .../interpreter/instruction_result.md | 2794 ++ .../interpreter/instructions/arithmetic.md | 2061 ++ .../interpreter/instructions/bitwise.md | 3135 +++ .../interpreter/instructions/contract.md | 8422 ++++++ .../instructions/contract/call_helpers.md | 966 + .../interpreter/instructions/control.md | 2999 +++ .../interpreter/instructions/data.md | 1663 ++ .../interpreter/instructions/host.md | 5307 ++++ .../interpreter/instructions/host_env.md | 2220 ++ .../interpreter/instructions/i256.md | 1209 + .../interpreter/instructions/memory.md | 2046 ++ .../interpreter/instructions/stack.md | 1354 + .../interpreter/instructions/system.md | 5231 ++++ .../interpreter/instructions/utility.md | 112 + .../translations/interpreter/interpreter.md | 3587 +++ .../interpreter/interpreter/analysis.md | 7004 +++++ .../interpreter/interpreter/contract.md | 693 + .../interpreter/interpreter/shared_memory.md | 2160 ++ .../interpreter/interpreter/stack.md | 3427 +++ .../interpreter/interpreter_action.md | 902 + .../interpreter_action/call_inputs.md | 2248 ++ .../interpreter_action/call_outcome.md | 420 + .../interpreter_action/create_inputs.md | 787 + .../interpreter_action/create_outcome.md | 367 + .../interpreter_action/eof_create_inputs.md | 635 + .../interpreter_action/eof_create_outcome.md | 459 + .../translations/interpreter/opcode.md | 21275 ++++++++++++++++ .../interpreter/opcode/eof_printer.md | 974 + .../translations/precompile/blake2.md | 1946 ++ .../revm-coq/translations/precompile/bn128.md | 3477 +++ .../revm-coq/translations/precompile/hash.md | 476 + .../translations/precompile/identity.md | 140 + .../precompile/kzg_point_evaluation.md | 846 + .../revm-coq/translations/precompile/lib.md | 2753 ++ .../translations/precompile/modexp.md | 1786 ++ .../translations/precompile/secp256k1.md | 898 + .../translations/precompile/utilities.md | 716 + .../translations/primitives/bytecode.md | 1363 + .../translations/primitives/bytecode/eof.md | 1734 ++ .../primitives/bytecode/eof/body.md | 2775 ++ .../primitives/bytecode/eof/decode_helpers.md | 229 + .../primitives/bytecode/eof/header.md | 4345 ++++ .../primitives/bytecode/eof/types_section.md | 1136 + .../primitives/bytecode/legacy.md | 732 + .../primitives/bytecode/legacy/jump_map.md | 568 + .../translations/primitives/constants.md | 136 + .../revm-coq/translations/primitives/db.md | 1565 ++ .../translations/primitives/db/components.md | 728 + .../primitives/db/components/block_hash.md | 437 + .../primitives/db/components/state.md | 945 + .../revm-coq/translations/primitives/env.md | 7708 ++++++ .../primitives/env/handler_cfg.md | 1186 + .../primitives/kzg/env_settings.md | 650 + .../primitives/kzg/trusted_setup_points.md | 2520 ++ .../translations/primitives/precompile.md | 1778 ++ .../translations/primitives/result.md | 7767 ++++++ .../translations/primitives/specification.md | 4587 ++++ .../revm-coq/translations/primitives/state.md | 2577 ++ .../translations/primitives/utilities.md | 262 + .../revm-coq/translations/revm/builder.md | 2614 ++ .../revm-coq/translations/revm/context.md | 367 + .../revm/context/context_precompiles.md | 1309 + .../translations/revm/context/evm_context.md | 2150 ++ .../revm/context/inner_evm_context.md | 4596 ++++ .../revm-coq/translations/revm/db/emptydb.md | 513 + .../translations/revm/db/in_memory_db.md | 5267 ++++ .../revm/db/states/account_status.md | 1669 ++ .../revm/db/states/bundle_account.md | 4500 ++++ .../revm/db/states/bundle_state.md | 9027 +++++++ .../translations/revm/db/states/cache.md | 1523 ++ .../revm/db/states/cache_account.md | 3285 +++ .../translations/revm/db/states/changes.md | 1405 + .../revm/db/states/plain_account.md | 469 + .../translations/revm/db/states/reverts.md | 3486 +++ .../translations/revm/db/states/state.md | 3316 +++ .../revm/db/states/state_builder.md | 1263 + .../revm/db/states/transition_account.md | 2139 ++ .../revm/db/states/transition_state.md | 557 + .../revm-coq/translations/revm/evm.md | 6499 +++++ .../revm-coq/translations/revm/frame.md | 1764 ++ .../revm-coq/translations/revm/handler.md | 1649 ++ .../revm/handler/handle_types/execution.md | 1545 ++ .../handler/handle_types/post_execution.md | 728 + .../handler/handle_types/pre_execution.md | 403 + .../revm/handler/handle_types/validation.md | 418 + .../revm/handler/mainnet/execution.md | 1323 + .../revm/handler/mainnet/post_execution.md | 1323 + .../revm/handler/mainnet/pre_execution.md | 891 + .../revm/handler/mainnet/validation.md | 761 + .../translations/revm/handler/register.md | 184 + .../revm-coq/translations/revm/inspector.md | 779 + .../revm/inspector/customprinter.md | 1234 + .../translations/revm/inspector/gas.md | 572 + .../revm/inspector/handler_register.md | 5242 ++++ .../translations/revm/inspector/noop.md | 240 + .../translations/revm/journaled_state.md | 10924 ++++++++ .../revm-python-spec/revm-verif/revm-verif.md | 7 + .../revm/interpreter/src/function_stack.md | 70 + .../revm-verif/revm/interpreter/src/gas.md | 139 + .../revm/interpreter/src/gas/calc.md | 418 + .../revm/interpreter/src/gas/constants.md | 59 + .../revm-verif/revm/interpreter/src/host.md | 102 + .../revm/interpreter/src/host/dummy.md | 130 + .../interpreter/src/instruction_result.md | 357 + .../revm/interpreter/src/instructions.md | 22 + .../src/instructions/arithmetic.md | 104 + .../interpreter/src/instructions/bitwise.md | 408 + .../interpreter/src/instructions/contract.md | 644 + .../src/instructions/contract/call_helpers.md | 75 + .../interpreter/src/instructions/control.md | 337 + .../revm/interpreter/src/instructions/data.md | 220 + .../revm/interpreter/src/instructions/host.md | 257 + .../src/instructions/host/call_helpers.md | 79 + .../interpreter/src/instructions/host_env.md | 86 + .../revm/interpreter/src/instructions/i256.md | 248 + .../interpreter/src/instructions/macros.md | 373 + .../interpreter/src/instructions/memory.md | 62 + .../interpreter/src/instructions/stack.md | 165 + .../interpreter/src/instructions/system.md | 216 + .../interpreter/src/instructions/utility.md | 13 + .../revm/interpreter/src/interpreter.md | 453 + .../interpreter/src/interpreter/analysis.md | 598 + .../interpreter/src/interpreter/contract.md | 98 + .../revm/interpreter/src/interpreter/serde.md | 248 + .../src/interpreter/shared_memory.md | 413 + .../revm/interpreter/src/interpreter/stack.md | 453 + .../interpreter/src/interpreter_action.md | 74 + .../src/interpreter_action/call_inputs.md | 198 + .../src/interpreter_action/call_outcome.md | 97 + .../src/interpreter_action/create_inputs.md | 57 + .../src/interpreter_action/create_outcome.md | 76 + .../interpreter_action/eof_create_inputs.md | 48 + .../interpreter_action/eof_create_outcome.md | 94 + .../revm-verif/revm/interpreter/src/lib.md | 54 + .../revm-verif/revm/interpreter/src/macros.md | 29 + .../revm-verif/revm/interpreter/src/opcode.md | 913 + .../interpreter/src/opcode/eof_printer.md | 73 + .../revm-verif/revm/interpreter/tests/eof.md | 190 + .../revm/precompile/benches/bench.md | 133 + .../revm-verif/revm/precompile/src/blake2.md | 140 + .../revm-verif/revm/precompile/src/bn128.md | 495 + .../revm-verif/revm/precompile/src/hash.md | 48 + .../revm/precompile/src/identity.md | 29 + .../precompile/src/kzg_point_evaluation.md | 126 + .../revm-verif/revm/precompile/src/lib.md | 274 + .../revm-verif/revm/precompile/src/modexp.md | 388 + .../revm/precompile/src/secp256k1.md | 97 + .../revm/precompile/src/utilities.md | 182 + .../revm/primitives/src/bytecode.md | 154 + .../revm/primitives/src/bytecode/eof.md | 162 + .../revm/primitives/src/bytecode/eof/body.md | 115 + .../src/bytecode/eof/decode_helpers.md | 26 + .../primitives/src/bytecode/eof/header.md | 263 + .../src/bytecode/eof/types_section.md | 68 + .../revm/primitives/src/bytecode/legacy.md | 74 + .../src/bytecode/legacy/jump_map.md | 42 + .../revm/primitives/src/constants.md | 68 + .../revm-verif/revm/primitives/src/db.md | 151 + .../revm/primitives/src/db/components.md | 89 + .../src/db/components/block_hash.md | 51 + .../primitives/src/db/components/state.md | 79 + .../revm-verif/revm/primitives/src/env.md | 797 + .../revm/primitives/src/env/handler_cfg.md | 165 + .../revm-verif/revm/primitives/src/kzg.md | 15 + .../revm/primitives/src/kzg/env_settings.md | 65 + .../src/kzg/trusted_setup_points.md | 139 + .../revm-verif/revm/primitives/src/lib.md | 54 + .../revm/primitives/src/precompile.md | 196 + .../revm-verif/revm/primitives/src/result.md | 452 + .../revm/primitives/src/specification.md | 431 + .../revm-verif/revm/primitives/src/state.md | 357 + .../revm/primitives/src/utilities.md | 176 + .../revm-verif/revm/revm/benches/bench.md | 145 + .../revm-verif/revm/revm/src/builder.md | 651 + .../revm-verif/revm/revm/src/context.md | 102 + .../revm/src/context/context_precompiles.md | 159 + .../revm/revm/src/context/evm_context.md | 406 + .../revm/src/context/inner_evm_context.md | 512 + .../revm-verif/revm/revm/src/db.md | 28 + .../revm-verif/revm/revm/src/db/alloydb.md | 186 + .../revm-verif/revm/revm/src/db/emptydb.md | 145 + .../revm-verif/revm/revm/src/db/ethersdb.md | 181 + .../revm/revm/src/db/in_memory_db.md | 497 + .../revm-verif/revm/revm/src/db/states.md | 32 + .../revm/revm/src/db/states/account_status.md | 258 + .../revm/revm/src/db/states/bundle_account.md | 375 + .../revm/revm/src/db/states/bundle_state.md | 1110 + .../revm/revm/src/db/states/cache.md | 159 + .../revm/revm/src/db/states/cache_account.md | 320 + .../revm/revm/src/db/states/changes.md | 77 + .../revm/revm/src/db/states/plain_account.md | 45 + .../revm/revm/src/db/states/reverts.md | 221 + .../revm/revm/src/db/states/state.md | 799 + .../revm/revm/src/db/states/state_builder.md | 177 + .../revm/src/db/states/transition_account.md | 152 + .../revm/src/db/states/transition_state.md | 43 + .../revm-verif/revm/revm/src/evm.md | 505 + .../revm-verif/revm/revm/src/frame.md | 308 + .../revm-verif/revm/revm/src/handler.md | 237 + .../revm/revm/src/handler/handle_types.md | 31 + .../src/handler/handle_types/execution.md | 264 + .../handler/handle_types/post_execution.md | 118 + .../src/handler/handle_types/pre_execution.md | 64 + .../src/handler/handle_types/validation.md | 66 + .../revm/revm/src/handler/mainnet.md | 21 + .../revm/src/handler/mainnet/execution.md | 241 + .../src/handler/mainnet/post_execution.md | 131 + .../revm/src/handler/mainnet/pre_execution.md | 94 + .../revm/src/handler/mainnet/validation.md | 61 + .../revm/revm/src/handler/register.md | 34 + .../revm-verif/revm/revm/src/inspector.md | 172 + .../revm/revm/src/inspector/customprinter.md | 160 + .../revm/revm/src/inspector/eip3155.md | 292 + .../revm-verif/revm/revm/src/inspector/gas.md | 226 + .../revm/src/inspector/handler_register.md | 431 + .../revm/revm/src/inspector/noop.md | 12 + .../revm/revm/src/journaled_state.md | 855 + .../revm-verif/revm/revm/src/lib.md | 65 + .../revm-verif/revm/revm/src/optimism.md | 16 + .../revm/src/optimism/handler_register.md | 638 + .../revm/revm/src/optimism/l1block.md | 319 + .../revm-verif/revm/revm/src/test_utils.md | 8 + .../revm-verif/spec-coq/__init__.md | 64 + .../spec-coq/arrow_glacier/__init__.md | 30 + .../spec-coq/arrow_glacier/blocks.md | 93 + .../spec-coq/arrow_glacier/bloom.md | 223 + .../revm-verif/spec-coq/arrow_glacier/fork.md | 3592 +++ .../spec-coq/arrow_glacier/fork_types.md | 109 + .../spec-coq/arrow_glacier/state.md | 1391 + .../spec-coq/arrow_glacier/transactions.md | 306 + .../revm-verif/spec-coq/arrow_glacier/trie.md | 1645 ++ .../spec-coq/arrow_glacier/utils/__init__.md | 16 + .../spec-coq/arrow_glacier/utils/address.md | 247 + .../arrow_glacier/utils/hexadecimal.md | 173 + .../spec-coq/arrow_glacier/utils/message.md | 278 + .../spec-coq/arrow_glacier/vm/__init__.md | 273 + .../spec-coq/arrow_glacier/vm/exceptions.md | 181 + .../spec-coq/arrow_glacier/vm/gas.md | 938 + .../arrow_glacier/vm/instructions/__init__.md | 82 + .../vm/instructions/arithmetic.md | 1272 + .../arrow_glacier/vm/instructions/bitwise.md | 706 + .../arrow_glacier/vm/instructions/block.md | 426 + .../vm/instructions/comparison.md | 484 + .../vm/instructions/control_flow.md | 382 + .../vm/instructions/environment.md | 1610 ++ .../arrow_glacier/vm/instructions/keccak.md | 200 + .../arrow_glacier/vm/instructions/log.md | 269 + .../arrow_glacier/vm/instructions/memory.md | 417 + .../arrow_glacier/vm/instructions/stack.md | 976 + .../arrow_glacier/vm/instructions/storage.md | 512 + .../arrow_glacier/vm/instructions/system.md | 2276 ++ .../spec-coq/arrow_glacier/vm/interpreter.md | 695 + .../spec-coq/arrow_glacier/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 124 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/blake2f.md | 144 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 80 + .../vm/precompiled_contracts/modexp.md | 700 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/arrow_glacier/vm/runtime.md | 169 + .../spec-coq/arrow_glacier/vm/stack.md | 139 + .../revm-verif/spec-coq/base_types.md | 4517 ++++ .../revm-verif/spec-coq/berlin/__init__.md | 31 + .../revm-verif/spec-coq/berlin/blocks.md | 93 + .../revm-verif/spec-coq/berlin/bloom.md | 223 + .../revm-verif/spec-coq/berlin/fork.md | 3143 +++ .../revm-verif/spec-coq/berlin/fork_types.md | 109 + .../revm-verif/spec-coq/berlin/state.md | 1391 + .../spec-coq/berlin/transactions.md | 235 + .../revm-verif/spec-coq/berlin/trie.md | 1645 ++ .../spec-coq/berlin/utils/__init__.md | 16 + .../spec-coq/berlin/utils/address.md | 247 + .../spec-coq/berlin/utils/hexadecimal.md | 173 + .../spec-coq/berlin/utils/message.md | 278 + .../revm-verif/spec-coq/berlin/vm/__init__.md | 273 + .../spec-coq/berlin/vm/exceptions.md | 171 + .../revm-verif/spec-coq/berlin/vm/gas.md | 948 + .../berlin/vm/instructions/__init__.md | 82 + .../berlin/vm/instructions/arithmetic.md | 1272 + .../berlin/vm/instructions/bitwise.md | 706 + .../spec-coq/berlin/vm/instructions/block.md | 426 + .../berlin/vm/instructions/comparison.md | 484 + .../berlin/vm/instructions/control_flow.md | 382 + .../berlin/vm/instructions/environment.md | 1564 ++ .../spec-coq/berlin/vm/instructions/keccak.md | 200 + .../spec-coq/berlin/vm/instructions/log.md | 269 + .../spec-coq/berlin/vm/instructions/memory.md | 417 + .../spec-coq/berlin/vm/instructions/stack.md | 976 + .../berlin/vm/instructions/storage.md | 512 + .../spec-coq/berlin/vm/instructions/system.md | 2329 ++ .../spec-coq/berlin/vm/interpreter.md | 693 + .../revm-verif/spec-coq/berlin/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 124 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/blake2f.md | 144 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 80 + .../berlin/vm/precompiled_contracts/modexp.md | 700 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../berlin/vm/precompiled_contracts/sha256.md | 118 + .../revm-verif/spec-coq/berlin/vm/runtime.md | 169 + .../revm-verif/spec-coq/berlin/vm/stack.md | 139 + .../revm-verif/spec-coq/byzantium/__init__.md | 31 + .../revm-verif/spec-coq/byzantium/blocks.md | 91 + .../revm-verif/spec-coq/byzantium/bloom.md | 223 + .../revm-verif/spec-coq/byzantium/fork.md | 2862 +++ .../spec-coq/byzantium/fork_types.md | 109 + .../revm-verif/spec-coq/byzantium/state.md | 1215 + .../spec-coq/byzantium/transactions.md | 63 + .../revm-verif/spec-coq/byzantium/trie.md | 1639 ++ .../spec-coq/byzantium/utils/__init__.md | 16 + .../spec-coq/byzantium/utils/address.md | 160 + .../spec-coq/byzantium/utils/hexadecimal.md | 173 + .../spec-coq/byzantium/utils/message.md | 224 + .../spec-coq/byzantium/vm/__init__.md | 255 + .../spec-coq/byzantium/vm/exceptions.md | 161 + .../revm-verif/spec-coq/byzantium/vm/gas.md | 938 + .../byzantium/vm/instructions/__init__.md | 82 + .../byzantium/vm/instructions/arithmetic.md | 1272 + .../byzantium/vm/instructions/bitwise.md | 400 + .../byzantium/vm/instructions/block.md | 380 + .../byzantium/vm/instructions/comparison.md | 484 + .../byzantium/vm/instructions/control_flow.md | 382 + .../byzantium/vm/instructions/environment.md | 1279 + .../byzantium/vm/instructions/keccak.md | 200 + .../spec-coq/byzantium/vm/instructions/log.md | 269 + .../byzantium/vm/instructions/memory.md | 417 + .../byzantium/vm/instructions/stack.md | 976 + .../byzantium/vm/instructions/storage.md | 265 + .../byzantium/vm/instructions/system.md | 1985 ++ .../spec-coq/byzantium/vm/interpreter.md | 677 + .../spec-coq/byzantium/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 114 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 75 + .../vm/precompiled_contracts/modexp.md | 560 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/byzantium/vm/runtime.md | 169 + .../revm-verif/spec-coq/byzantium/vm/stack.md | 139 + .../revm-verif/spec-coq/cancun/__init__.md | 32 + .../revm-verif/spec-coq/cancun/blocks.md | 104 + .../revm-verif/spec-coq/cancun/bloom.md | 223 + .../revm-verif/spec-coq/cancun/fork.md | 3340 +++ .../revm-verif/spec-coq/cancun/fork_types.md | 113 + .../revm-verif/spec-coq/cancun/state.md | 1646 ++ .../spec-coq/cancun/transactions.md | 379 + .../revm-verif/spec-coq/cancun/trie.md | 1654 ++ .../spec-coq/cancun/utils/__init__.md | 16 + .../spec-coq/cancun/utils/address.md | 247 + .../spec-coq/cancun/utils/hexadecimal.md | 173 + .../spec-coq/cancun/utils/message.md | 278 + .../revm-verif/spec-coq/cancun/vm/__init__.md | 277 + .../spec-coq/cancun/vm/exceptions.md | 191 + .../revm-verif/spec-coq/cancun/vm/gas.md | 1257 + .../cancun/vm/instructions/__init__.md | 82 + .../cancun/vm/instructions/arithmetic.md | 1272 + .../cancun/vm/instructions/bitwise.md | 706 + .../spec-coq/cancun/vm/instructions/block.md | 468 + .../cancun/vm/instructions/comparison.md | 484 + .../cancun/vm/instructions/control_flow.md | 382 + .../cancun/vm/instructions/environment.md | 1767 ++ .../spec-coq/cancun/vm/instructions/keccak.md | 200 + .../spec-coq/cancun/vm/instructions/log.md | 269 + .../spec-coq/cancun/vm/instructions/memory.md | 560 + .../spec-coq/cancun/vm/instructions/stack.md | 1008 + .../cancun/vm/instructions/storage.md | 655 + .../spec-coq/cancun/vm/instructions/system.md | 2347 ++ .../spec-coq/cancun/vm/interpreter.md | 702 + .../revm-verif/spec-coq/cancun/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 134 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/blake2f.md | 144 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 85 + .../cancun/vm/precompiled_contracts/modexp.md | 700 + .../precompiled_contracts/point_evaluation.md | 231 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../cancun/vm/precompiled_contracts/sha256.md | 118 + .../revm-verif/spec-coq/cancun/vm/runtime.md | 169 + .../revm-verif/spec-coq/cancun/vm/stack.md | 139 + .../spec-coq/constantinople/__init__.md | 31 + .../spec-coq/constantinople/blocks.md | 91 + .../spec-coq/constantinople/bloom.md | 223 + .../spec-coq/constantinople/fork.md | 2862 +++ .../spec-coq/constantinople/fork_types.md | 109 + .../spec-coq/constantinople/state.md | 1215 + .../spec-coq/constantinople/transactions.md | 63 + .../spec-coq/constantinople/trie.md | 1639 ++ .../spec-coq/constantinople/utils/__init__.md | 16 + .../spec-coq/constantinople/utils/address.md | 247 + .../constantinople/utils/hexadecimal.md | 173 + .../spec-coq/constantinople/utils/message.md | 224 + .../spec-coq/constantinople/vm/__init__.md | 255 + .../spec-coq/constantinople/vm/exceptions.md | 161 + .../spec-coq/constantinople/vm/gas.md | 948 + .../vm/instructions/__init__.md | 82 + .../vm/instructions/arithmetic.md | 1272 + .../constantinople/vm/instructions/bitwise.md | 706 + .../constantinople/vm/instructions/block.md | 380 + .../vm/instructions/comparison.md | 484 + .../vm/instructions/control_flow.md | 382 + .../vm/instructions/environment.md | 1391 + .../constantinople/vm/instructions/keccak.md | 200 + .../constantinople/vm/instructions/log.md | 269 + .../constantinople/vm/instructions/memory.md | 417 + .../constantinople/vm/instructions/stack.md | 976 + .../constantinople/vm/instructions/storage.md | 265 + .../constantinople/vm/instructions/system.md | 2178 ++ .../spec-coq/constantinople/vm/interpreter.md | 677 + .../spec-coq/constantinople/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 114 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 75 + .../vm/precompiled_contracts/modexp.md | 560 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/constantinople/vm/runtime.md | 169 + .../spec-coq/constantinople/vm/stack.md | 139 + .../revm-verif/spec-coq/crypto/__init__.md | 16 + .../revm-verif/spec-coq/crypto/alt_bn128.md | 821 + .../revm-verif/spec-coq/crypto/blake2.md | 834 + .../spec-coq/crypto/elliptic_curve.md | 794 + .../spec-coq/crypto/finite_field.md | 2325 ++ .../revm-verif/spec-coq/crypto/hash.md | 142 + .../spec-coq/crypto/simulations/hash.md | 32 + .../revm-verif/spec-coq/dao_fork/__init__.md | 31 + .../revm-verif/spec-coq/dao_fork/blocks.md | 91 + .../revm-verif/spec-coq/dao_fork/bloom.md | 223 + .../revm-verif/spec-coq/dao_fork/dao.md | 102 + .../revm-verif/spec-coq/dao_fork/fork.md | 2691 ++ .../spec-coq/dao_fork/fork_types.md | 109 + .../revm-verif/spec-coq/dao_fork/state.md | 998 + .../spec-coq/dao_fork/transactions.md | 63 + .../revm-verif/spec-coq/dao_fork/trie.md | 1639 ++ .../spec-coq/dao_fork/utils/__init__.md | 16 + .../spec-coq/dao_fork/utils/address.md | 159 + .../spec-coq/dao_fork/utils/hexadecimal.md | 173 + .../spec-coq/dao_fork/utils/message.md | 220 + .../spec-coq/dao_fork/vm/__init__.md | 151 + .../spec-coq/dao_fork/vm/exceptions.md | 131 + .../revm-verif/spec-coq/dao_fork/vm/gas.md | 874 + .../dao_fork/vm/instructions/__init__.md | 82 + .../dao_fork/vm/instructions/arithmetic.md | 1272 + .../dao_fork/vm/instructions/bitwise.md | 400 + .../dao_fork/vm/instructions/block.md | 380 + .../dao_fork/vm/instructions/comparison.md | 484 + .../dao_fork/vm/instructions/control_flow.md | 382 + .../dao_fork/vm/instructions/environment.md | 1053 + .../dao_fork/vm/instructions/keccak.md | 200 + .../spec-coq/dao_fork/vm/instructions/log.md | 254 + .../dao_fork/vm/instructions/memory.md | 417 + .../dao_fork/vm/instructions/stack.md | 976 + .../dao_fork/vm/instructions/storage.md | 250 + .../dao_fork/vm/instructions/system.md | 1420 ++ .../spec-coq/dao_fork/vm/interpreter.md | 593 + .../revm-verif/spec-coq/dao_fork/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 74 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 57 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/dao_fork/vm/runtime.md | 169 + .../revm-verif/spec-coq/dao_fork/vm/stack.md | 139 + .../revm-verif/spec-coq/ethash.md | 1272 + .../revm-verif/spec-coq/exceptions.md | 66 + .../revm-verif/spec-coq/fork_criteria.md | 297 + .../revm-verif/spec-coq/frontier/__init__.md | 29 + .../revm-verif/spec-coq/frontier/blocks.md | 91 + .../revm-verif/spec-coq/frontier/bloom.md | 223 + .../revm-verif/spec-coq/frontier/fork.md | 2571 ++ .../spec-coq/frontier/fork_types.md | 109 + .../revm-verif/spec-coq/frontier/state.md | 998 + .../spec-coq/frontier/transactions.md | 59 + .../revm-verif/spec-coq/frontier/trie.md | 1633 ++ .../spec-coq/frontier/utils/__init__.md | 16 + .../spec-coq/frontier/utils/address.md | 159 + .../spec-coq/frontier/utils/hexadecimal.md | 173 + .../spec-coq/frontier/utils/message.md | 218 + .../spec-coq/frontier/vm/__init__.md | 158 + .../spec-coq/frontier/vm/exceptions.md | 131 + .../revm-verif/spec-coq/frontier/vm/gas.md | 874 + .../frontier/vm/instructions/__init__.md | 82 + .../frontier/vm/instructions/arithmetic.md | 1272 + .../frontier/vm/instructions/bitwise.md | 400 + .../frontier/vm/instructions/block.md | 380 + .../frontier/vm/instructions/comparison.md | 484 + .../frontier/vm/instructions/control_flow.md | 382 + .../frontier/vm/instructions/environment.md | 1053 + .../frontier/vm/instructions/keccak.md | 200 + .../spec-coq/frontier/vm/instructions/log.md | 254 + .../frontier/vm/instructions/memory.md | 417 + .../frontier/vm/instructions/stack.md | 976 + .../frontier/vm/instructions/storage.md | 250 + .../frontier/vm/instructions/system.md | 1269 + .../spec-coq/frontier/vm/interpreter.md | 603 + .../revm-verif/spec-coq/frontier/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 74 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 57 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/frontier/vm/runtime.md | 169 + .../revm-verif/spec-coq/frontier/vm/stack.md | 139 + .../revm-verif/spec-coq/genesis.md | 500 + .../spec-coq/gray_glacier/__init__.md | 30 + .../spec-coq/gray_glacier/blocks.md | 93 + .../revm-verif/spec-coq/gray_glacier/bloom.md | 223 + .../revm-verif/spec-coq/gray_glacier/fork.md | 3592 +++ .../spec-coq/gray_glacier/fork_types.md | 109 + .../revm-verif/spec-coq/gray_glacier/state.md | 1391 + .../spec-coq/gray_glacier/transactions.md | 306 + .../revm-verif/spec-coq/gray_glacier/trie.md | 1645 ++ .../spec-coq/gray_glacier/utils/__init__.md | 16 + .../spec-coq/gray_glacier/utils/address.md | 247 + .../gray_glacier/utils/hexadecimal.md | 173 + .../spec-coq/gray_glacier/utils/message.md | 278 + .../spec-coq/gray_glacier/vm/__init__.md | 273 + .../spec-coq/gray_glacier/vm/exceptions.md | 181 + .../spec-coq/gray_glacier/vm/gas.md | 938 + .../gray_glacier/vm/instructions/__init__.md | 82 + .../vm/instructions/arithmetic.md | 1272 + .../gray_glacier/vm/instructions/bitwise.md | 706 + .../gray_glacier/vm/instructions/block.md | 426 + .../vm/instructions/comparison.md | 484 + .../vm/instructions/control_flow.md | 382 + .../vm/instructions/environment.md | 1610 ++ .../gray_glacier/vm/instructions/keccak.md | 200 + .../gray_glacier/vm/instructions/log.md | 269 + .../gray_glacier/vm/instructions/memory.md | 417 + .../gray_glacier/vm/instructions/stack.md | 976 + .../gray_glacier/vm/instructions/storage.md | 512 + .../gray_glacier/vm/instructions/system.md | 2276 ++ .../spec-coq/gray_glacier/vm/interpreter.md | 695 + .../spec-coq/gray_glacier/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 124 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/blake2f.md | 144 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 80 + .../vm/precompiled_contracts/modexp.md | 700 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/gray_glacier/vm/runtime.md | 169 + .../spec-coq/gray_glacier/vm/stack.md | 139 + .../revm-verif/spec-coq/homestead/__init__.md | 32 + .../revm-verif/spec-coq/homestead/blocks.md | 91 + .../revm-verif/spec-coq/homestead/bloom.md | 223 + .../revm-verif/spec-coq/homestead/fork.md | 2630 ++ .../spec-coq/homestead/fork_types.md | 109 + .../revm-verif/spec-coq/homestead/state.md | 998 + .../spec-coq/homestead/transactions.md | 63 + .../revm-verif/spec-coq/homestead/trie.md | 1639 ++ .../spec-coq/homestead/utils/__init__.md | 16 + .../spec-coq/homestead/utils/address.md | 159 + .../spec-coq/homestead/utils/hexadecimal.md | 173 + .../spec-coq/homestead/utils/message.md | 220 + .../spec-coq/homestead/vm/__init__.md | 158 + .../spec-coq/homestead/vm/exceptions.md | 131 + .../revm-verif/spec-coq/homestead/vm/gas.md | 874 + .../homestead/vm/instructions/__init__.md | 82 + .../homestead/vm/instructions/arithmetic.md | 1272 + .../homestead/vm/instructions/bitwise.md | 400 + .../homestead/vm/instructions/block.md | 380 + .../homestead/vm/instructions/comparison.md | 484 + .../homestead/vm/instructions/control_flow.md | 382 + .../homestead/vm/instructions/environment.md | 1053 + .../homestead/vm/instructions/keccak.md | 200 + .../spec-coq/homestead/vm/instructions/log.md | 254 + .../homestead/vm/instructions/memory.md | 417 + .../homestead/vm/instructions/stack.md | 976 + .../homestead/vm/instructions/storage.md | 250 + .../homestead/vm/instructions/system.md | 1420 ++ .../spec-coq/homestead/vm/interpreter.md | 601 + .../spec-coq/homestead/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 74 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 57 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/homestead/vm/runtime.md | 169 + .../revm-verif/spec-coq/homestead/vm/stack.md | 139 + .../revm-verif/spec-coq/istanbul/__init__.md | 31 + .../revm-verif/spec-coq/istanbul/blocks.md | 91 + .../revm-verif/spec-coq/istanbul/bloom.md | 223 + .../revm-verif/spec-coq/istanbul/fork.md | 2862 +++ .../spec-coq/istanbul/fork_types.md | 109 + .../revm-verif/spec-coq/istanbul/state.md | 1391 + .../spec-coq/istanbul/transactions.md | 63 + .../revm-verif/spec-coq/istanbul/trie.md | 1639 ++ .../spec-coq/istanbul/utils/__init__.md | 16 + .../spec-coq/istanbul/utils/address.md | 247 + .../spec-coq/istanbul/utils/hexadecimal.md | 173 + .../spec-coq/istanbul/utils/message.md | 224 + .../spec-coq/istanbul/vm/__init__.md | 257 + .../spec-coq/istanbul/vm/exceptions.md | 171 + .../revm-verif/spec-coq/istanbul/vm/gas.md | 968 + .../istanbul/vm/instructions/__init__.md | 82 + .../istanbul/vm/instructions/arithmetic.md | 1272 + .../istanbul/vm/instructions/bitwise.md | 706 + .../istanbul/vm/instructions/block.md | 426 + .../istanbul/vm/instructions/comparison.md | 484 + .../istanbul/vm/instructions/control_flow.md | 382 + .../istanbul/vm/instructions/environment.md | 1444 ++ .../istanbul/vm/instructions/keccak.md | 200 + .../spec-coq/istanbul/vm/instructions/log.md | 269 + .../istanbul/vm/instructions/memory.md | 417 + .../istanbul/vm/instructions/stack.md | 976 + .../istanbul/vm/instructions/storage.md | 433 + .../istanbul/vm/instructions/system.md | 2178 ++ .../spec-coq/istanbul/vm/interpreter.md | 693 + .../revm-verif/spec-coq/istanbul/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 124 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/blake2f.md | 144 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 80 + .../vm/precompiled_contracts/modexp.md | 560 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/istanbul/vm/runtime.md | 169 + .../revm-verif/spec-coq/istanbul/vm/stack.md | 139 + .../revm-verif/spec-coq/london/__init__.md | 30 + .../revm-verif/spec-coq/london/blocks.md | 93 + .../revm-verif/spec-coq/london/bloom.md | 223 + .../revm-verif/spec-coq/london/fork.md | 3628 +++ .../revm-verif/spec-coq/london/fork_types.md | 109 + .../revm-verif/spec-coq/london/state.md | 1391 + .../spec-coq/london/transactions.md | 306 + .../revm-verif/spec-coq/london/trie.md | 1645 ++ .../spec-coq/london/utils/__init__.md | 16 + .../spec-coq/london/utils/address.md | 247 + .../spec-coq/london/utils/hexadecimal.md | 173 + .../spec-coq/london/utils/message.md | 278 + .../revm-verif/spec-coq/london/vm/__init__.md | 273 + .../spec-coq/london/vm/exceptions.md | 181 + .../revm-verif/spec-coq/london/vm/gas.md | 938 + .../london/vm/instructions/__init__.md | 82 + .../london/vm/instructions/arithmetic.md | 1272 + .../london/vm/instructions/bitwise.md | 706 + .../spec-coq/london/vm/instructions/block.md | 426 + .../london/vm/instructions/comparison.md | 484 + .../london/vm/instructions/control_flow.md | 382 + .../london/vm/instructions/environment.md | 1610 ++ .../spec-coq/london/vm/instructions/keccak.md | 200 + .../spec-coq/london/vm/instructions/log.md | 269 + .../spec-coq/london/vm/instructions/memory.md | 417 + .../spec-coq/london/vm/instructions/stack.md | 976 + .../london/vm/instructions/storage.md | 512 + .../spec-coq/london/vm/instructions/system.md | 2276 ++ .../spec-coq/london/vm/interpreter.md | 695 + .../revm-verif/spec-coq/london/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 124 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/blake2f.md | 144 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 80 + .../london/vm/precompiled_contracts/modexp.md | 700 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../london/vm/precompiled_contracts/sha256.md | 118 + .../revm-verif/spec-coq/london/vm/runtime.md | 169 + .../revm-verif/spec-coq/london/vm/stack.md | 139 + .../spec-coq/muir_glacier/__init__.md | 30 + .../spec-coq/muir_glacier/blocks.md | 91 + .../revm-verif/spec-coq/muir_glacier/bloom.md | 223 + .../revm-verif/spec-coq/muir_glacier/fork.md | 2862 +++ .../spec-coq/muir_glacier/fork_types.md | 109 + .../revm-verif/spec-coq/muir_glacier/state.md | 1391 + .../spec-coq/muir_glacier/transactions.md | 63 + .../revm-verif/spec-coq/muir_glacier/trie.md | 1639 ++ .../spec-coq/muir_glacier/utils/__init__.md | 16 + .../spec-coq/muir_glacier/utils/address.md | 247 + .../muir_glacier/utils/hexadecimal.md | 173 + .../spec-coq/muir_glacier/utils/message.md | 224 + .../spec-coq/muir_glacier/vm/__init__.md | 257 + .../spec-coq/muir_glacier/vm/exceptions.md | 171 + .../spec-coq/muir_glacier/vm/gas.md | 968 + .../muir_glacier/vm/instructions/__init__.md | 82 + .../vm/instructions/arithmetic.md | 1272 + .../muir_glacier/vm/instructions/bitwise.md | 706 + .../muir_glacier/vm/instructions/block.md | 426 + .../vm/instructions/comparison.md | 484 + .../vm/instructions/control_flow.md | 382 + .../vm/instructions/environment.md | 1444 ++ .../muir_glacier/vm/instructions/keccak.md | 200 + .../muir_glacier/vm/instructions/log.md | 269 + .../muir_glacier/vm/instructions/memory.md | 417 + .../muir_glacier/vm/instructions/stack.md | 976 + .../muir_glacier/vm/instructions/storage.md | 433 + .../muir_glacier/vm/instructions/system.md | 2178 ++ .../spec-coq/muir_glacier/vm/interpreter.md | 693 + .../spec-coq/muir_glacier/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 124 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/blake2f.md | 144 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 80 + .../vm/precompiled_contracts/modexp.md | 560 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/muir_glacier/vm/runtime.md | 169 + .../spec-coq/muir_glacier/vm/stack.md | 139 + .../revm-verif/spec-coq/paris/__init__.md | 34 + .../revm-verif/spec-coq/paris/blocks.md | 93 + .../revm-verif/spec-coq/paris/bloom.md | 223 + .../revm-verif/spec-coq/paris/fork.md | 2748 ++ .../revm-verif/spec-coq/paris/fork_types.md | 109 + .../spec-coq/paris/simulations/fork_types.md | 18 + .../spec-coq/paris/simulations/state.md | 11 + .../revm-verif/spec-coq/paris/state.md | 1360 + .../revm-verif/spec-coq/paris/transactions.md | 306 + .../revm-verif/spec-coq/paris/trie.md | 1645 ++ .../spec-coq/paris/utils/__init__.md | 16 + .../spec-coq/paris/utils/address.md | 247 + .../spec-coq/paris/utils/hexadecimal.md | 173 + .../spec-coq/paris/utils/message.md | 278 + .../revm-verif/spec-coq/paris/vm/__init__.md | 273 + .../spec-coq/paris/vm/exceptions.md | 181 + .../revm-verif/spec-coq/paris/vm/gas.md | 938 + .../paris/vm/instructions/__init__.md | 82 + .../paris/vm/instructions/arithmetic.md | 1272 + .../spec-coq/paris/vm/instructions/bitwise.md | 706 + .../spec-coq/paris/vm/instructions/block.md | 468 + .../paris/vm/instructions/comparison.md | 484 + .../paris/vm/instructions/control_flow.md | 382 + .../paris/vm/instructions/environment.md | 1610 ++ .../spec-coq/paris/vm/instructions/keccak.md | 200 + .../spec-coq/paris/vm/instructions/log.md | 269 + .../spec-coq/paris/vm/instructions/memory.md | 417 + .../vm/instructions/proofs/arithmetic.md | 80 + .../vm/instructions/simulations/arithmetic.md | 262 + .../vm/instructions/simulations/bitwise.md | 375 + .../spec-coq/paris/vm/instructions/stack.md | 976 + .../spec-coq/paris/vm/instructions/storage.md | 512 + .../spec-coq/paris/vm/instructions/system.md | 2276 ++ .../spec-coq/paris/vm/interpreter.md | 697 + .../revm-verif/spec-coq/paris/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 124 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../paris/vm/precompiled_contracts/blake2f.md | 144 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../paris/vm/precompiled_contracts/mapping.md | 80 + .../paris/vm/precompiled_contracts/modexp.md | 700 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../paris/vm/precompiled_contracts/sha256.md | 118 + .../revm-verif/spec-coq/paris/vm/runtime.md | 169 + .../spec-coq/paris/vm/simulations/__init__.md | 125 + .../paris/vm/simulations/exceptions.md | 26 + .../spec-coq/paris/vm/simulations/gas.md | 61 + .../paris/vm/simulations/proofs/__init__.md | 40 + .../paris/vm/simulations/proofs/exceptions.md | 41 + .../paris/vm/simulations/proofs/stack.md | 190 + .../spec-coq/paris/vm/simulations/stack.md | 41 + .../revm-verif/spec-coq/paris/vm/stack.md | 139 + .../revm-verif/spec-coq/rlp.md | 2600 ++ .../revm-verif/spec-coq/shanghai/__init__.md | 31 + .../revm-verif/spec-coq/shanghai/blocks.md | 104 + .../revm-verif/spec-coq/shanghai/bloom.md | 223 + .../revm-verif/spec-coq/shanghai/fork.md | 2958 +++ .../spec-coq/shanghai/fork_types.md | 109 + .../revm-verif/spec-coq/shanghai/state.md | 1385 + .../spec-coq/shanghai/transactions.md | 306 + .../revm-verif/spec-coq/shanghai/trie.md | 1654 ++ .../spec-coq/shanghai/utils/__init__.md | 16 + .../spec-coq/shanghai/utils/address.md | 247 + .../spec-coq/shanghai/utils/hexadecimal.md | 173 + .../spec-coq/shanghai/utils/message.md | 278 + .../spec-coq/shanghai/vm/__init__.md | 273 + .../spec-coq/shanghai/vm/exceptions.md | 181 + .../revm-verif/spec-coq/shanghai/vm/gas.md | 981 + .../shanghai/vm/instructions/__init__.md | 82 + .../shanghai/vm/instructions/arithmetic.md | 1272 + .../shanghai/vm/instructions/bitwise.md | 706 + .../shanghai/vm/instructions/block.md | 468 + .../shanghai/vm/instructions/comparison.md | 484 + .../shanghai/vm/instructions/control_flow.md | 382 + .../shanghai/vm/instructions/environment.md | 1610 ++ .../shanghai/vm/instructions/keccak.md | 200 + .../spec-coq/shanghai/vm/instructions/log.md | 269 + .../shanghai/vm/instructions/memory.md | 417 + .../shanghai/vm/instructions/stack.md | 1008 + .../shanghai/vm/instructions/storage.md | 512 + .../shanghai/vm/instructions/system.md | 2344 ++ .../spec-coq/shanghai/vm/interpreter.md | 697 + .../revm-verif/spec-coq/shanghai/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 124 + .../vm/precompiled_contracts/alt_bn128.md | 803 + .../vm/precompiled_contracts/blake2f.md | 144 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 80 + .../vm/precompiled_contracts/modexp.md | 700 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/shanghai/vm/runtime.md | 169 + .../revm-verif/spec-coq/shanghai/vm/stack.md | 139 + .../spec-coq/simulations/base_types.md | 326 + .../spec-coq/simulations/exceptions.md | 13 + .../spec-coq/simulations/proofs/base_types.md | 19 + .../spec-coq/simulations/proofs/exceptions.md | 22 + .../spec-coq/spurious_dragon/__init__.md | 33 + .../spec-coq/spurious_dragon/blocks.md | 91 + .../spec-coq/spurious_dragon/bloom.md | 223 + .../spec-coq/spurious_dragon/fork.md | 2828 ++ .../spec-coq/spurious_dragon/fork_types.md | 109 + .../spec-coq/spurious_dragon/state.md | 1215 + .../spec-coq/spurious_dragon/transactions.md | 63 + .../spec-coq/spurious_dragon/trie.md | 1639 ++ .../spurious_dragon/utils/__init__.md | 16 + .../spec-coq/spurious_dragon/utils/address.md | 160 + .../spurious_dragon/utils/hexadecimal.md | 173 + .../spec-coq/spurious_dragon/utils/message.md | 221 + .../spec-coq/spurious_dragon/vm/__init__.md | 255 + .../spec-coq/spurious_dragon/vm/exceptions.md | 131 + .../spec-coq/spurious_dragon/vm/gas.md | 928 + .../vm/instructions/__init__.md | 82 + .../vm/instructions/arithmetic.md | 1272 + .../vm/instructions/bitwise.md | 400 + .../spurious_dragon/vm/instructions/block.md | 380 + .../vm/instructions/comparison.md | 484 + .../vm/instructions/control_flow.md | 382 + .../vm/instructions/environment.md | 1053 + .../spurious_dragon/vm/instructions/keccak.md | 200 + .../spurious_dragon/vm/instructions/log.md | 254 + .../spurious_dragon/vm/instructions/memory.md | 417 + .../spurious_dragon/vm/instructions/stack.md | 976 + .../vm/instructions/storage.md | 250 + .../spurious_dragon/vm/instructions/system.md | 1628 ++ .../spurious_dragon/vm/interpreter.md | 675 + .../spec-coq/spurious_dragon/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 74 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 57 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/spurious_dragon/vm/runtime.md | 169 + .../spec-coq/spurious_dragon/vm/stack.md | 139 + .../spec-coq/tangerine_whistle/__init__.md | 32 + .../spec-coq/tangerine_whistle/blocks.md | 91 + .../spec-coq/tangerine_whistle/bloom.md | 223 + .../spec-coq/tangerine_whistle/fork.md | 2630 ++ .../spec-coq/tangerine_whistle/fork_types.md | 109 + .../spec-coq/tangerine_whistle/state.md | 998 + .../tangerine_whistle/transactions.md | 63 + .../spec-coq/tangerine_whistle/trie.md | 1639 ++ .../tangerine_whistle/utils/__init__.md | 16 + .../tangerine_whistle/utils/address.md | 160 + .../tangerine_whistle/utils/hexadecimal.md | 173 + .../tangerine_whistle/utils/message.md | 221 + .../spec-coq/tangerine_whistle/vm/__init__.md | 158 + .../tangerine_whistle/vm/exceptions.md | 131 + .../spec-coq/tangerine_whistle/vm/gas.md | 928 + .../vm/instructions/__init__.md | 82 + .../vm/instructions/arithmetic.md | 1272 + .../vm/instructions/bitwise.md | 400 + .../vm/instructions/block.md | 380 + .../vm/instructions/comparison.md | 484 + .../vm/instructions/control_flow.md | 382 + .../vm/instructions/environment.md | 1053 + .../vm/instructions/keccak.md | 200 + .../tangerine_whistle/vm/instructions/log.md | 254 + .../vm/instructions/memory.md | 417 + .../vm/instructions/stack.md | 976 + .../vm/instructions/storage.md | 250 + .../vm/instructions/system.md | 1582 ++ .../tangerine_whistle/vm/interpreter.md | 601 + .../spec-coq/tangerine_whistle/vm/memory.md | 186 + .../vm/precompiled_contracts/__init__.md | 74 + .../vm/precompiled_contracts/ecrecover.md | 313 + .../vm/precompiled_contracts/identity.md | 106 + .../vm/precompiled_contracts/mapping.md | 57 + .../vm/precompiled_contracts/ripemd160.md | 137 + .../vm/precompiled_contracts/sha256.md | 118 + .../spec-coq/tangerine_whistle/vm/runtime.md | 169 + .../spec-coq/tangerine_whistle/vm/stack.md | 139 + .../revm-verif/spec-coq/trace.md | 139 + .../revm-verif/spec-coq/utils/__init__.md | 16 + .../revm-verif/spec-coq/utils/byte.md | 97 + .../revm-verif/spec-coq/utils/ensure.md | 68 + .../revm-verif/spec-coq/utils/hexadecimal.md | 546 + .../revm-verif/spec-coq/utils/numeric.md | 535 + .../spec-coq/utils/safe_arithmetic.md | 115 + .../revm-verif/spec/__init__.md | 33 + .../revm-verif/spec/arrow_glacier/__init__.md | 14 + .../revm-verif/spec/arrow_glacier/blocks.md | 85 + .../revm-verif/spec/arrow_glacier/bloom.md | 90 + .../revm-verif/spec/arrow_glacier/fork.md | 1259 + .../spec/arrow_glacier/fork_types.md | 73 + .../revm-verif/spec/arrow_glacier/state.md | 617 + .../spec/arrow_glacier/transactions.md | 126 + .../revm-verif/spec/arrow_glacier/trie.md | 470 + .../spec/arrow_glacier/utils/__init__.md | 9 + .../spec/arrow_glacier/utils/address.md | 97 + .../spec/arrow_glacier/utils/hexadecimal.md | 74 + .../spec/arrow_glacier/utils/message.md | 121 + .../spec/arrow_glacier/vm/__init__.md | 152 + .../spec/arrow_glacier/vm/exceptions.md | 138 + .../revm-verif/spec/arrow_glacier/vm/gas.md | 245 + .../arrow_glacier/vm/instructions/__init__.md | 360 + .../vm/instructions/arithmetic.md | 375 + .../arrow_glacier/vm/instructions/bitwise.md | 246 + .../arrow_glacier/vm/instructions/block.md | 212 + .../vm/instructions/comparison.md | 184 + .../vm/instructions/control_flow.md | 177 + .../vm/instructions/environment.md | 543 + .../arrow_glacier/vm/instructions/keccak.md | 69 + .../spec/arrow_glacier/vm/instructions/log.md | 94 + .../arrow_glacier/vm/instructions/memory.md | 146 + .../arrow_glacier/vm/instructions/stack.md | 214 + .../arrow_glacier/vm/instructions/storage.md | 132 + .../arrow_glacier/vm/instructions/system.md | 669 + .../spec/arrow_glacier/vm/interpreter.md | 314 + .../spec/arrow_glacier/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 44 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/blake2f.md | 50 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 52 + .../vm/precompiled_contracts/modexp.md | 174 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../spec/arrow_glacier/vm/runtime.md | 73 + .../revm-verif/spec/arrow_glacier/vm/stack.md | 65 + .../revm-verif/spec/base_types.md | 990 + .../revm-verif/spec/berlin/__init__.md | 15 + .../revm-verif/spec/berlin/blocks.md | 84 + .../revm-verif/spec/berlin/bloom.md | 90 + .../revm-verif/spec/berlin/fork.md | 1106 + .../revm-verif/spec/berlin/fork_types.md | 73 + .../revm-verif/spec/berlin/state.md | 617 + .../revm-verif/spec/berlin/transactions.md | 98 + .../revm-verif/spec/berlin/trie.md | 470 + .../revm-verif/spec/berlin/utils/__init__.md | 9 + .../revm-verif/spec/berlin/utils/address.md | 97 + .../spec/berlin/utils/hexadecimal.md | 74 + .../revm-verif/spec/berlin/utils/message.md | 121 + .../revm-verif/spec/berlin/vm/__init__.md | 151 + .../revm-verif/spec/berlin/vm/exceptions.md | 130 + .../revm-verif/spec/berlin/vm/gas.md | 246 + .../spec/berlin/vm/instructions/__init__.md | 358 + .../spec/berlin/vm/instructions/arithmetic.md | 375 + .../spec/berlin/vm/instructions/bitwise.md | 246 + .../spec/berlin/vm/instructions/block.md | 212 + .../spec/berlin/vm/instructions/comparison.md | 184 + .../berlin/vm/instructions/control_flow.md | 177 + .../berlin/vm/instructions/environment.md | 520 + .../spec/berlin/vm/instructions/keccak.md | 69 + .../spec/berlin/vm/instructions/log.md | 94 + .../spec/berlin/vm/instructions/memory.md | 146 + .../spec/berlin/vm/instructions/stack.md | 214 + .../spec/berlin/vm/instructions/storage.md | 132 + .../spec/berlin/vm/instructions/system.md | 680 + .../revm-verif/spec/berlin/vm/interpreter.md | 311 + .../revm-verif/spec/berlin/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 44 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/blake2f.md | 50 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 52 + .../berlin/vm/precompiled_contracts/modexp.md | 174 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../berlin/vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/berlin/vm/runtime.md | 73 + .../revm-verif/spec/berlin/vm/stack.md | 65 + .../revm-verif/spec/byzantium/__init__.md | 15 + .../revm-verif/spec/byzantium/blocks.md | 84 + .../revm-verif/spec/byzantium/bloom.md | 90 + .../revm-verif/spec/byzantium/fork.md | 1036 + .../revm-verif/spec/byzantium/fork_types.md | 72 + .../revm-verif/spec/byzantium/state.md | 558 + .../revm-verif/spec/byzantium/transactions.md | 39 + .../revm-verif/spec/byzantium/trie.md | 470 + .../spec/byzantium/utils/__init__.md | 9 + .../spec/byzantium/utils/address.md | 68 + .../spec/byzantium/utils/hexadecimal.md | 74 + .../spec/byzantium/utils/message.md | 103 + .../revm-verif/spec/byzantium/vm/__init__.md | 144 + .../spec/byzantium/vm/exceptions.md | 122 + .../revm-verif/spec/byzantium/vm/gas.md | 245 + .../byzantium/vm/instructions/__init__.md | 344 + .../byzantium/vm/instructions/arithmetic.md | 375 + .../spec/byzantium/vm/instructions/bitwise.md | 160 + .../spec/byzantium/vm/instructions/block.md | 189 + .../byzantium/vm/instructions/comparison.md | 184 + .../byzantium/vm/instructions/control_flow.md | 177 + .../byzantium/vm/instructions/environment.md | 444 + .../spec/byzantium/vm/instructions/keccak.md | 69 + .../spec/byzantium/vm/instructions/log.md | 94 + .../spec/byzantium/vm/instructions/memory.md | 146 + .../spec/byzantium/vm/instructions/stack.md | 214 + .../spec/byzantium/vm/instructions/storage.md | 92 + .../spec/byzantium/vm/instructions/system.md | 575 + .../spec/byzantium/vm/interpreter.md | 302 + .../revm-verif/spec/byzantium/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 43 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 49 + .../vm/precompiled_contracts/modexp.md | 92 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/byzantium/vm/runtime.md | 73 + .../revm-verif/spec/byzantium/vm/stack.md | 65 + .../revm-verif/spec/cancun/__init__.md | 16 + .../revm-verif/spec/cancun/blocks.md | 111 + .../revm-verif/spec/cancun/bloom.md | 90 + .../revm-verif/spec/cancun/fork.md | 1155 + .../revm-verif/spec/cancun/fork_types.md | 74 + .../revm-verif/spec/cancun/state.md | 719 + .../revm-verif/spec/cancun/transactions.md | 156 + .../revm-verif/spec/cancun/trie.md | 473 + .../revm-verif/spec/cancun/utils/__init__.md | 9 + .../revm-verif/spec/cancun/utils/address.md | 97 + .../spec/cancun/utils/hexadecimal.md | 74 + .../revm-verif/spec/cancun/utils/message.md | 121 + .../revm-verif/spec/cancun/vm/__init__.md | 155 + .../revm-verif/spec/cancun/vm/exceptions.md | 146 + .../revm-verif/spec/cancun/vm/gas.md | 360 + .../spec/cancun/vm/instructions/__init__.md | 372 + .../spec/cancun/vm/instructions/arithmetic.md | 375 + .../spec/cancun/vm/instructions/bitwise.md | 246 + .../spec/cancun/vm/instructions/block.md | 254 + .../spec/cancun/vm/instructions/comparison.md | 184 + .../cancun/vm/instructions/control_flow.md | 177 + .../cancun/vm/instructions/environment.md | 596 + .../spec/cancun/vm/instructions/keccak.md | 69 + .../spec/cancun/vm/instructions/log.md | 94 + .../spec/cancun/vm/instructions/memory.md | 181 + .../spec/cancun/vm/instructions/stack.md | 218 + .../spec/cancun/vm/instructions/storage.md | 188 + .../spec/cancun/vm/instructions/system.md | 695 + .../revm-verif/spec/cancun/vm/interpreter.md | 314 + .../revm-verif/spec/cancun/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 46 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/blake2f.md | 50 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 55 + .../cancun/vm/precompiled_contracts/modexp.md | 174 + .../precompiled_contracts/point_evaluation.md | 82 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../cancun/vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/cancun/vm/runtime.md | 73 + .../revm-verif/spec/cancun/vm/stack.md | 65 + .../spec/constantinople/__init__.md | 15 + .../revm-verif/spec/constantinople/blocks.md | 84 + .../revm-verif/spec/constantinople/bloom.md | 90 + .../revm-verif/spec/constantinople/fork.md | 1036 + .../spec/constantinople/fork_types.md | 73 + .../revm-verif/spec/constantinople/state.md | 558 + .../spec/constantinople/transactions.md | 39 + .../revm-verif/spec/constantinople/trie.md | 470 + .../spec/constantinople/utils/__init__.md | 9 + .../spec/constantinople/utils/address.md | 96 + .../spec/constantinople/utils/hexadecimal.md | 74 + .../spec/constantinople/utils/message.md | 103 + .../spec/constantinople/vm/__init__.md | 144 + .../spec/constantinople/vm/exceptions.md | 122 + .../revm-verif/spec/constantinople/vm/gas.md | 246 + .../vm/instructions/__init__.md | 354 + .../vm/instructions/arithmetic.md | 375 + .../constantinople/vm/instructions/bitwise.md | 246 + .../constantinople/vm/instructions/block.md | 189 + .../vm/instructions/comparison.md | 184 + .../vm/instructions/control_flow.md | 177 + .../vm/instructions/environment.md | 475 + .../constantinople/vm/instructions/keccak.md | 69 + .../constantinople/vm/instructions/log.md | 94 + .../constantinople/vm/instructions/memory.md | 146 + .../constantinople/vm/instructions/stack.md | 214 + .../constantinople/vm/instructions/storage.md | 92 + .../constantinople/vm/instructions/system.md | 641 + .../spec/constantinople/vm/interpreter.md | 303 + .../spec/constantinople/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 43 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 49 + .../vm/precompiled_contracts/modexp.md | 92 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../spec/constantinople/vm/runtime.md | 73 + .../spec/constantinople/vm/stack.md | 65 + .../revm-verif/spec/crypto/__init__.md | 9 + .../revm-verif/spec/crypto/alt_bn128.md | 201 + .../revm-verif/spec/crypto/blake2.md | 256 + .../revm-verif/spec/crypto/elliptic_curve.md | 163 + .../revm-verif/spec/crypto/finite_field.md | 410 + .../revm-verif/spec/crypto/hash.md | 62 + .../revm-verif/spec/dao_fork/__init__.md | 15 + .../revm-verif/spec/dao_fork/blocks.md | 84 + .../revm-verif/spec/dao_fork/bloom.md | 90 + .../revm-verif/spec/dao_fork/dao.md | 163 + .../revm-verif/spec/dao_fork/fork.md | 994 + .../revm-verif/spec/dao_fork/fork_types.md | 73 + .../revm-verif/spec/dao_fork/state.md | 479 + .../revm-verif/spec/dao_fork/transactions.md | 39 + .../revm-verif/spec/dao_fork/trie.md | 470 + .../spec/dao_fork/utils/__init__.md | 9 + .../revm-verif/spec/dao_fork/utils/address.md | 67 + .../spec/dao_fork/utils/hexadecimal.md | 74 + .../revm-verif/spec/dao_fork/utils/message.md | 97 + .../revm-verif/spec/dao_fork/vm/__init__.md | 120 + .../revm-verif/spec/dao_fork/vm/exceptions.md | 93 + .../revm-verif/spec/dao_fork/vm/gas.md | 213 + .../spec/dao_fork/vm/instructions/__init__.md | 336 + .../dao_fork/vm/instructions/arithmetic.md | 375 + .../spec/dao_fork/vm/instructions/bitwise.md | 160 + .../spec/dao_fork/vm/instructions/block.md | 189 + .../dao_fork/vm/instructions/comparison.md | 184 + .../dao_fork/vm/instructions/control_flow.md | 177 + .../dao_fork/vm/instructions/environment.md | 381 + .../spec/dao_fork/vm/instructions/keccak.md | 69 + .../spec/dao_fork/vm/instructions/log.md | 91 + .../spec/dao_fork/vm/instructions/memory.md | 146 + .../spec/dao_fork/vm/instructions/stack.md | 214 + .../spec/dao_fork/vm/instructions/storage.md | 89 + .../spec/dao_fork/vm/instructions/system.md | 434 + .../spec/dao_fork/vm/interpreter.md | 271 + .../revm-verif/spec/dao_fork/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 34 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 39 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/dao_fork/vm/runtime.md | 73 + .../revm-verif/spec/dao_fork/vm/stack.md | 65 + .../revm-verif/spec/ethash.md | 433 + .../revm-verif/spec/exceptions.md | 44 + .../revm-verif/spec/fork_criteria.md | 142 + .../revm-verif/spec/frontier/__init__.md | 13 + .../revm-verif/spec/frontier/blocks.md | 84 + .../revm-verif/spec/frontier/bloom.md | 90 + .../revm-verif/spec/frontier/fork.md | 963 + .../revm-verif/spec/frontier/fork_types.md | 73 + .../revm-verif/spec/frontier/state.md | 479 + .../revm-verif/spec/frontier/transactions.md | 38 + .../revm-verif/spec/frontier/trie.md | 471 + .../spec/frontier/utils/__init__.md | 9 + .../revm-verif/spec/frontier/utils/address.md | 67 + .../spec/frontier/utils/hexadecimal.md | 74 + .../revm-verif/spec/frontier/utils/message.md | 93 + .../revm-verif/spec/frontier/vm/__init__.md | 120 + .../revm-verif/spec/frontier/vm/exceptions.md | 93 + .../revm-verif/spec/frontier/vm/gas.md | 213 + .../spec/frontier/vm/instructions/__init__.md | 334 + .../frontier/vm/instructions/arithmetic.md | 375 + .../spec/frontier/vm/instructions/bitwise.md | 160 + .../spec/frontier/vm/instructions/block.md | 189 + .../frontier/vm/instructions/comparison.md | 184 + .../frontier/vm/instructions/control_flow.md | 177 + .../frontier/vm/instructions/environment.md | 381 + .../spec/frontier/vm/instructions/keccak.md | 69 + .../spec/frontier/vm/instructions/log.md | 91 + .../spec/frontier/vm/instructions/memory.md | 146 + .../spec/frontier/vm/instructions/stack.md | 214 + .../spec/frontier/vm/instructions/storage.md | 89 + .../spec/frontier/vm/instructions/system.md | 381 + .../spec/frontier/vm/interpreter.md | 277 + .../revm-verif/spec/frontier/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 34 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 39 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/frontier/vm/runtime.md | 73 + .../revm-verif/spec/frontier/vm/stack.md | 65 + .../revm-verif/spec/genesis.md | 209 + .../revm-verif/spec/gray_glacier/__init__.md | 14 + .../revm-verif/spec/gray_glacier/blocks.md | 85 + .../revm-verif/spec/gray_glacier/bloom.md | 90 + .../revm-verif/spec/gray_glacier/fork.md | 1259 + .../spec/gray_glacier/fork_types.md | 73 + .../revm-verif/spec/gray_glacier/state.md | 617 + .../spec/gray_glacier/transactions.md | 126 + .../revm-verif/spec/gray_glacier/trie.md | 470 + .../spec/gray_glacier/utils/__init__.md | 9 + .../spec/gray_glacier/utils/address.md | 97 + .../spec/gray_glacier/utils/hexadecimal.md | 74 + .../spec/gray_glacier/utils/message.md | 121 + .../spec/gray_glacier/vm/__init__.md | 152 + .../spec/gray_glacier/vm/exceptions.md | 138 + .../revm-verif/spec/gray_glacier/vm/gas.md | 245 + .../gray_glacier/vm/instructions/__init__.md | 360 + .../vm/instructions/arithmetic.md | 375 + .../gray_glacier/vm/instructions/bitwise.md | 246 + .../gray_glacier/vm/instructions/block.md | 212 + .../vm/instructions/comparison.md | 184 + .../vm/instructions/control_flow.md | 177 + .../vm/instructions/environment.md | 543 + .../gray_glacier/vm/instructions/keccak.md | 69 + .../spec/gray_glacier/vm/instructions/log.md | 94 + .../gray_glacier/vm/instructions/memory.md | 146 + .../gray_glacier/vm/instructions/stack.md | 214 + .../gray_glacier/vm/instructions/storage.md | 132 + .../gray_glacier/vm/instructions/system.md | 669 + .../spec/gray_glacier/vm/interpreter.md | 314 + .../revm-verif/spec/gray_glacier/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 44 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/blake2f.md | 50 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 52 + .../vm/precompiled_contracts/modexp.md | 174 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../spec/gray_glacier/vm/runtime.md | 73 + .../revm-verif/spec/gray_glacier/vm/stack.md | 65 + .../revm-verif/spec/homestead/__init__.md | 16 + .../revm-verif/spec/homestead/blocks.md | 84 + .../revm-verif/spec/homestead/bloom.md | 90 + .../revm-verif/spec/homestead/fork.md | 977 + .../revm-verif/spec/homestead/fork_types.md | 73 + .../revm-verif/spec/homestead/state.md | 479 + .../revm-verif/spec/homestead/transactions.md | 39 + .../revm-verif/spec/homestead/trie.md | 470 + .../spec/homestead/utils/__init__.md | 9 + .../spec/homestead/utils/address.md | 67 + .../spec/homestead/utils/hexadecimal.md | 74 + .../spec/homestead/utils/message.md | 97 + .../revm-verif/spec/homestead/vm/__init__.md | 121 + .../spec/homestead/vm/exceptions.md | 93 + .../revm-verif/spec/homestead/vm/gas.md | 213 + .../homestead/vm/instructions/__init__.md | 336 + .../homestead/vm/instructions/arithmetic.md | 375 + .../spec/homestead/vm/instructions/bitwise.md | 160 + .../spec/homestead/vm/instructions/block.md | 189 + .../homestead/vm/instructions/comparison.md | 184 + .../homestead/vm/instructions/control_flow.md | 177 + .../homestead/vm/instructions/environment.md | 381 + .../spec/homestead/vm/instructions/keccak.md | 69 + .../spec/homestead/vm/instructions/log.md | 91 + .../spec/homestead/vm/instructions/memory.md | 146 + .../spec/homestead/vm/instructions/stack.md | 214 + .../spec/homestead/vm/instructions/storage.md | 89 + .../spec/homestead/vm/instructions/system.md | 434 + .../spec/homestead/vm/interpreter.md | 279 + .../revm-verif/spec/homestead/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 34 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 39 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/homestead/vm/runtime.md | 73 + .../revm-verif/spec/homestead/vm/stack.md | 65 + .../revm-verif/spec/istanbul/__init__.md | 15 + .../revm-verif/spec/istanbul/blocks.md | 84 + .../revm-verif/spec/istanbul/bloom.md | 90 + .../revm-verif/spec/istanbul/fork.md | 1037 + .../revm-verif/spec/istanbul/fork_types.md | 73 + .../revm-verif/spec/istanbul/state.md | 617 + .../revm-verif/spec/istanbul/transactions.md | 39 + .../revm-verif/spec/istanbul/trie.md | 470 + .../spec/istanbul/utils/__init__.md | 9 + .../revm-verif/spec/istanbul/utils/address.md | 97 + .../spec/istanbul/utils/hexadecimal.md | 74 + .../revm-verif/spec/istanbul/utils/message.md | 103 + .../revm-verif/spec/istanbul/vm/__init__.md | 145 + .../revm-verif/spec/istanbul/vm/exceptions.md | 130 + .../revm-verif/spec/istanbul/vm/gas.md | 248 + .../spec/istanbul/vm/instructions/__init__.md | 358 + .../istanbul/vm/instructions/arithmetic.md | 375 + .../spec/istanbul/vm/instructions/bitwise.md | 246 + .../spec/istanbul/vm/instructions/block.md | 212 + .../istanbul/vm/instructions/comparison.md | 184 + .../istanbul/vm/instructions/control_flow.md | 177 + .../istanbul/vm/instructions/environment.md | 502 + .../spec/istanbul/vm/instructions/keccak.md | 69 + .../spec/istanbul/vm/instructions/log.md | 94 + .../spec/istanbul/vm/instructions/memory.md | 146 + .../spec/istanbul/vm/instructions/stack.md | 214 + .../spec/istanbul/vm/instructions/storage.md | 118 + .../spec/istanbul/vm/instructions/system.md | 641 + .../spec/istanbul/vm/interpreter.md | 312 + .../revm-verif/spec/istanbul/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 44 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/blake2f.md | 50 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 52 + .../vm/precompiled_contracts/modexp.md | 92 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/istanbul/vm/runtime.md | 73 + .../revm-verif/spec/istanbul/vm/stack.md | 65 + .../revm-verif/spec/london/__init__.md | 14 + .../revm-verif/spec/london/blocks.md | 85 + .../revm-verif/spec/london/bloom.md | 90 + .../revm-verif/spec/london/fork.md | 1267 + .../revm-verif/spec/london/fork_types.md | 73 + .../revm-verif/spec/london/state.md | 617 + .../revm-verif/spec/london/transactions.md | 126 + .../revm-verif/spec/london/trie.md | 470 + .../revm-verif/spec/london/utils/__init__.md | 9 + .../revm-verif/spec/london/utils/address.md | 97 + .../spec/london/utils/hexadecimal.md | 74 + .../revm-verif/spec/london/utils/message.md | 121 + .../revm-verif/spec/london/vm/__init__.md | 152 + .../revm-verif/spec/london/vm/exceptions.md | 138 + .../revm-verif/spec/london/vm/gas.md | 245 + .../spec/london/vm/instructions/__init__.md | 360 + .../spec/london/vm/instructions/arithmetic.md | 375 + .../spec/london/vm/instructions/bitwise.md | 246 + .../spec/london/vm/instructions/block.md | 212 + .../spec/london/vm/instructions/comparison.md | 184 + .../london/vm/instructions/control_flow.md | 177 + .../london/vm/instructions/environment.md | 543 + .../spec/london/vm/instructions/keccak.md | 69 + .../spec/london/vm/instructions/log.md | 94 + .../spec/london/vm/instructions/memory.md | 146 + .../spec/london/vm/instructions/stack.md | 214 + .../spec/london/vm/instructions/storage.md | 132 + .../spec/london/vm/instructions/system.md | 669 + .../revm-verif/spec/london/vm/interpreter.md | 314 + .../revm-verif/spec/london/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 44 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/blake2f.md | 50 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 52 + .../london/vm/precompiled_contracts/modexp.md | 174 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../london/vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/london/vm/runtime.md | 73 + .../revm-verif/spec/london/vm/stack.md | 65 + .../revm-verif/spec/muir_glacier/__init__.md | 13 + .../revm-verif/spec/muir_glacier/blocks.md | 84 + .../revm-verif/spec/muir_glacier/bloom.md | 90 + .../revm-verif/spec/muir_glacier/fork.md | 1037 + .../spec/muir_glacier/fork_types.md | 73 + .../revm-verif/spec/muir_glacier/state.md | 617 + .../spec/muir_glacier/transactions.md | 39 + .../revm-verif/spec/muir_glacier/trie.md | 470 + .../spec/muir_glacier/utils/__init__.md | 9 + .../spec/muir_glacier/utils/address.md | 97 + .../spec/muir_glacier/utils/hexadecimal.md | 74 + .../spec/muir_glacier/utils/message.md | 103 + .../spec/muir_glacier/vm/__init__.md | 145 + .../spec/muir_glacier/vm/exceptions.md | 130 + .../revm-verif/spec/muir_glacier/vm/gas.md | 248 + .../muir_glacier/vm/instructions/__init__.md | 358 + .../vm/instructions/arithmetic.md | 375 + .../muir_glacier/vm/instructions/bitwise.md | 246 + .../muir_glacier/vm/instructions/block.md | 212 + .../vm/instructions/comparison.md | 184 + .../vm/instructions/control_flow.md | 177 + .../vm/instructions/environment.md | 502 + .../muir_glacier/vm/instructions/keccak.md | 69 + .../spec/muir_glacier/vm/instructions/log.md | 94 + .../muir_glacier/vm/instructions/memory.md | 146 + .../muir_glacier/vm/instructions/stack.md | 214 + .../muir_glacier/vm/instructions/storage.md | 118 + .../muir_glacier/vm/instructions/system.md | 641 + .../spec/muir_glacier/vm/interpreter.md | 309 + .../revm-verif/spec/muir_glacier/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 44 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/blake2f.md | 50 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 52 + .../vm/precompiled_contracts/modexp.md | 92 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../spec/muir_glacier/vm/runtime.md | 73 + .../revm-verif/spec/muir_glacier/vm/stack.md | 65 + .../revm-verif/spec/paris/__init__.md | 22 + .../revm-verif/spec/paris/blocks.md | 85 + .../revm-verif/spec/paris/bloom.md | 90 + .../revm-verif/spec/paris/fork.md | 977 + .../revm-verif/spec/paris/fork_types.md | 73 + .../revm-verif/spec/paris/state.md | 597 + .../revm-verif/spec/paris/transactions.md | 126 + .../revm-verif/spec/paris/trie.md | 470 + .../revm-verif/spec/paris/utils/__init__.md | 9 + .../revm-verif/spec/paris/utils/address.md | 97 + .../spec/paris/utils/hexadecimal.md | 74 + .../revm-verif/spec/paris/utils/message.md | 121 + .../revm-verif/spec/paris/vm/__init__.md | 152 + .../revm-verif/spec/paris/vm/exceptions.md | 138 + .../revm-verif/spec/paris/vm/gas.md | 245 + .../spec/paris/vm/instructions/__init__.md | 360 + .../spec/paris/vm/instructions/arithmetic.md | 375 + .../spec/paris/vm/instructions/bitwise.md | 246 + .../spec/paris/vm/instructions/block.md | 254 + .../spec/paris/vm/instructions/comparison.md | 184 + .../paris/vm/instructions/control_flow.md | 177 + .../spec/paris/vm/instructions/environment.md | 543 + .../spec/paris/vm/instructions/keccak.md | 69 + .../spec/paris/vm/instructions/log.md | 94 + .../spec/paris/vm/instructions/memory.md | 146 + .../spec/paris/vm/instructions/stack.md | 214 + .../spec/paris/vm/instructions/storage.md | 132 + .../spec/paris/vm/instructions/system.md | 669 + .../revm-verif/spec/paris/vm/interpreter.md | 314 + .../revm-verif/spec/paris/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 44 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../paris/vm/precompiled_contracts/blake2f.md | 50 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../paris/vm/precompiled_contracts/mapping.md | 52 + .../paris/vm/precompiled_contracts/modexp.md | 174 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../paris/vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/paris/vm/runtime.md | 73 + .../revm-verif/spec/paris/vm/stack.md | 83 + docs/revm-python-spec/revm-verif/spec/rlp.md | 516 + .../revm-verif/spec/shanghai/__init__.md | 15 + .../revm-verif/spec/shanghai/blocks.md | 108 + .../revm-verif/spec/shanghai/bloom.md | 90 + .../revm-verif/spec/shanghai/fork.md | 1010 + .../revm-verif/spec/shanghai/fork_types.md | 73 + .../revm-verif/spec/shanghai/state.md | 612 + .../revm-verif/spec/shanghai/transactions.md | 126 + .../revm-verif/spec/shanghai/trie.md | 473 + .../spec/shanghai/utils/__init__.md | 9 + .../revm-verif/spec/shanghai/utils/address.md | 97 + .../spec/shanghai/utils/hexadecimal.md | 74 + .../revm-verif/spec/shanghai/utils/message.md | 121 + .../revm-verif/spec/shanghai/vm/__init__.md | 152 + .../revm-verif/spec/shanghai/vm/exceptions.md | 138 + .../revm-verif/spec/shanghai/vm/gas.md | 265 + .../spec/shanghai/vm/instructions/__init__.md | 362 + .../shanghai/vm/instructions/arithmetic.md | 375 + .../spec/shanghai/vm/instructions/bitwise.md | 246 + .../spec/shanghai/vm/instructions/block.md | 254 + .../shanghai/vm/instructions/comparison.md | 184 + .../shanghai/vm/instructions/control_flow.md | 177 + .../shanghai/vm/instructions/environment.md | 543 + .../spec/shanghai/vm/instructions/keccak.md | 69 + .../spec/shanghai/vm/instructions/log.md | 94 + .../spec/shanghai/vm/instructions/memory.md | 146 + .../spec/shanghai/vm/instructions/stack.md | 218 + .../spec/shanghai/vm/instructions/storage.md | 132 + .../spec/shanghai/vm/instructions/system.md | 692 + .../spec/shanghai/vm/interpreter.md | 314 + .../revm-verif/spec/shanghai/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 44 + .../vm/precompiled_contracts/alt_bn128.md | 162 + .../vm/precompiled_contracts/blake2f.md | 50 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 52 + .../vm/precompiled_contracts/modexp.md | 174 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../revm-verif/spec/shanghai/vm/runtime.md | 73 + .../revm-verif/spec/shanghai/vm/stack.md | 65 + .../spec/spurious_dragon/__init__.md | 17 + .../revm-verif/spec/spurious_dragon/blocks.md | 84 + .../revm-verif/spec/spurious_dragon/bloom.md | 90 + .../revm-verif/spec/spurious_dragon/fork.md | 1025 + .../spec/spurious_dragon/fork_types.md | 73 + .../revm-verif/spec/spurious_dragon/state.md | 558 + .../spec/spurious_dragon/transactions.md | 39 + .../revm-verif/spec/spurious_dragon/trie.md | 470 + .../spec/spurious_dragon/utils/__init__.md | 9 + .../spec/spurious_dragon/utils/address.md | 68 + .../spec/spurious_dragon/utils/hexadecimal.md | 74 + .../spec/spurious_dragon/utils/message.md | 98 + .../spec/spurious_dragon/vm/__init__.md | 142 + .../spec/spurious_dragon/vm/exceptions.md | 93 + .../revm-verif/spec/spurious_dragon/vm/gas.md | 244 + .../vm/instructions/__init__.md | 336 + .../vm/instructions/arithmetic.md | 375 + .../vm/instructions/bitwise.md | 160 + .../spurious_dragon/vm/instructions/block.md | 189 + .../vm/instructions/comparison.md | 184 + .../vm/instructions/control_flow.md | 177 + .../vm/instructions/environment.md | 381 + .../spurious_dragon/vm/instructions/keccak.md | 69 + .../spurious_dragon/vm/instructions/log.md | 91 + .../spurious_dragon/vm/instructions/memory.md | 146 + .../spurious_dragon/vm/instructions/stack.md | 214 + .../vm/instructions/storage.md | 89 + .../spurious_dragon/vm/instructions/system.md | 468 + .../spec/spurious_dragon/vm/interpreter.md | 295 + .../spec/spurious_dragon/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 34 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 39 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../spec/spurious_dragon/vm/runtime.md | 73 + .../spec/spurious_dragon/vm/stack.md | 65 + .../spec/tangerine_whistle/__init__.md | 16 + .../spec/tangerine_whistle/blocks.md | 84 + .../spec/tangerine_whistle/bloom.md | 90 + .../revm-verif/spec/tangerine_whistle/fork.md | 977 + .../spec/tangerine_whistle/fork_types.md | 73 + .../spec/tangerine_whistle/state.md | 479 + .../spec/tangerine_whistle/transactions.md | 39 + .../revm-verif/spec/tangerine_whistle/trie.md | 470 + .../spec/tangerine_whistle/utils/__init__.md | 9 + .../spec/tangerine_whistle/utils/address.md | 68 + .../tangerine_whistle/utils/hexadecimal.md | 74 + .../spec/tangerine_whistle/utils/message.md | 98 + .../spec/tangerine_whistle/vm/__init__.md | 121 + .../spec/tangerine_whistle/vm/exceptions.md | 93 + .../spec/tangerine_whistle/vm/gas.md | 244 + .../vm/instructions/__init__.md | 336 + .../vm/instructions/arithmetic.md | 375 + .../vm/instructions/bitwise.md | 160 + .../vm/instructions/block.md | 189 + .../vm/instructions/comparison.md | 184 + .../vm/instructions/control_flow.md | 177 + .../vm/instructions/environment.md | 381 + .../vm/instructions/keccak.md | 69 + .../tangerine_whistle/vm/instructions/log.md | 91 + .../vm/instructions/memory.md | 146 + .../vm/instructions/stack.md | 214 + .../vm/instructions/storage.md | 89 + .../vm/instructions/system.md | 457 + .../spec/tangerine_whistle/vm/interpreter.md | 279 + .../spec/tangerine_whistle/vm/memory.md | 86 + .../vm/precompiled_contracts/__init__.md | 34 + .../vm/precompiled_contracts/ecrecover.md | 67 + .../vm/precompiled_contracts/identity.md | 43 + .../vm/precompiled_contracts/mapping.md | 39 + .../vm/precompiled_contracts/ripemd160.md | 48 + .../vm/precompiled_contracts/sha256.md | 45 + .../spec/tangerine_whistle/vm/runtime.md | 73 + .../spec/tangerine_whistle/vm/stack.md | 65 + .../revm-python-spec/revm-verif/spec/trace.md | 116 + .../revm-verif/spec/utils/__init__.md | 9 + .../revm-verif/spec/utils/byte.md | 58 + .../revm-verif/spec/utils/ensure.md | 42 + .../revm-verif/spec/utils/hexadecimal.md | 223 + .../revm-verif/spec/utils/numeric.md | 207 + .../revm-verif/spec/utils/safe_arithmetic.md | 101 + docusaurus.config.js | 2 +- sidebars.js | 4 + 1592 files changed, 736062 insertions(+), 1 deletion(-) create mode 100644 docs/revm-python-spec/import_revm.py create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/dependencies.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/contract.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/function_stack.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/gas.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/instruction_result.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/shared_memory.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/stack.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/call_inputs.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/create_inputs.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/eof_create_inputs.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/body.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/header.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/type_section.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/links/primitives/env.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/instructions/macros.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter/gas.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter/stack.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/function_stack.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas/calc.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas/constants.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/host.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/host/dummy.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instruction_result.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/contract.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/contract/call_helpers.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/control.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/data.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/host.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/host_env.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/i256.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/utility.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/analysis.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/contract.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/shared_memory.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/stack.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/call_inputs.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/call_outcome.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/create_inputs.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/create_outcome.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/eof_create_inputs.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/eof_create_outcome.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/opcode.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/opcode/eof_printer.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/blake2.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/bn128.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/hash.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/identity.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/kzg_point_evaluation.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/lib.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/secp256k1.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/utilities.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/body.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/decode_helpers.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/header.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/types_section.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/legacy.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/legacy/jump_map.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/constants.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components/block_hash.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components/state.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/env.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/env/handler_cfg.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/kzg/env_settings.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/kzg/trusted_setup_points.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/precompile.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/result.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/specification.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/state.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/utilities.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/builder.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/context_precompiles.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/evm_context.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/inner_evm_context.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/emptydb.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/in_memory_db.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/account_status.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/bundle_account.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/bundle_state.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/cache.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/cache_account.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/changes.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/plain_account.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/reverts.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/state.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/state_builder.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/transition_account.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/transition_state.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/evm.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/frame.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/post_execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/pre_execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/validation.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/post_execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/pre_execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/validation.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/register.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/customprinter.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/gas.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/handler_register.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/noop.md create mode 100644 docs/revm-python-spec/revm-verif/revm-coq/translations/revm/journaled_state.md create mode 100644 docs/revm-python-spec/revm-verif/revm-verif.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/function_stack.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/gas.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/gas/calc.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/gas/constants.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/host.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/host/dummy.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instruction_result.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/contract.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/contract/call_helpers.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/control.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/data.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host/call_helpers.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host_env.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/i256.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/macros.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/utility.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/analysis.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/contract.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/serde.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/shared_memory.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/stack.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/call_inputs.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/call_outcome.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/create_inputs.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/create_outcome.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/eof_create_inputs.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/eof_create_outcome.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/lib.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/macros.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/opcode.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/src/opcode/eof_printer.md create mode 100644 docs/revm-python-spec/revm-verif/revm/interpreter/tests/eof.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/benches/bench.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/src/blake2.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/src/bn128.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/src/hash.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/src/identity.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/src/kzg_point_evaluation.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/src/lib.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/src/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/src/secp256k1.md create mode 100644 docs/revm-python-spec/revm-verif/revm/precompile/src/utilities.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/body.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/decode_helpers.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/header.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/types_section.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/legacy.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/legacy/jump_map.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/constants.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/db.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/db/components.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/db/components/block_hash.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/db/components/state.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/env.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/env/handler_cfg.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/kzg.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/kzg/env_settings.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/kzg/trusted_setup_points.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/lib.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/precompile.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/result.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/specification.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/state.md create mode 100644 docs/revm-python-spec/revm-verif/revm/primitives/src/utilities.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/benches/bench.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/builder.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/context.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/context/context_precompiles.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/context/evm_context.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/context/inner_evm_context.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/alloydb.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/emptydb.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/ethersdb.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/in_memory_db.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/account_status.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/bundle_account.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/bundle_state.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/cache.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/cache_account.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/changes.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/plain_account.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/reverts.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/state.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/state_builder.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/transition_account.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/db/states/transition_state.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/evm.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/frame.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/post_execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/pre_execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/validation.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/post_execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/pre_execution.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/validation.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/handler/register.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/inspector.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/inspector/customprinter.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/inspector/eip3155.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/inspector/gas.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/inspector/handler_register.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/inspector/noop.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/journaled_state.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/lib.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/optimism.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/optimism/handler_register.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/optimism/l1block.md create mode 100644 docs/revm-python-spec/revm-verif/revm/revm/src/test_utils.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/base_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/point_evaluation.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/crypto/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/crypto/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/crypto/blake2.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/crypto/elliptic_curve.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/crypto/finite_field.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/crypto/hash.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/crypto/simulations/hash.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/dao.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/ethash.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/fork_criteria.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/genesis.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/london/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/simulations/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/simulations/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/proofs/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/simulations/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/simulations/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/paris/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/rlp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/simulations/base_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/simulations/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/simulations/proofs/base_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/simulations/proofs/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/trace.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/utils/byte.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/utils/ensure.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/utils/numeric.md create mode 100644 docs/revm-python-spec/revm-verif/spec-coq/utils/safe_arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/base_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/berlin/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/byzantium/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/point_evaluation.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/cancun/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/constantinople/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/crypto/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/crypto/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/crypto/blake2.md create mode 100644 docs/revm-python-spec/revm-verif/spec/crypto/elliptic_curve.md create mode 100644 docs/revm-python-spec/revm-verif/spec/crypto/finite_field.md create mode 100644 docs/revm-python-spec/revm-verif/spec/crypto/hash.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/dao.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/dao_fork/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/ethash.md create mode 100644 docs/revm-python-spec/revm-verif/spec/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/fork_criteria.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/frontier/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/genesis.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/homestead/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/istanbul/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/london/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/paris/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/rlp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/alt_bn128.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/blake2f.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/modexp.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/shanghai/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/blocks.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/bloom.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/fork.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/fork_types.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/state.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/transactions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/trie.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/address.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/message.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/exceptions.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/gas.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/arithmetic.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/bitwise.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/block.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/comparison.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/control_flow.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/environment.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/keccak.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/log.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/storage.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/system.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/interpreter.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/memory.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/ecrecover.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/identity.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/mapping.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/ripemd160.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/sha256.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/runtime.md create mode 100644 docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/stack.md create mode 100644 docs/revm-python-spec/revm-verif/spec/trace.md create mode 100644 docs/revm-python-spec/revm-verif/spec/utils/__init__.md create mode 100644 docs/revm-python-spec/revm-verif/spec/utils/byte.md create mode 100644 docs/revm-python-spec/revm-verif/spec/utils/ensure.md create mode 100644 docs/revm-python-spec/revm-verif/spec/utils/hexadecimal.md create mode 100644 docs/revm-python-spec/revm-verif/spec/utils/numeric.md create mode 100644 docs/revm-python-spec/revm-verif/spec/utils/safe_arithmetic.md diff --git a/docs/revm-python-spec/import_revm.py b/docs/revm-python-spec/import_revm.py new file mode 100644 index 00000000..659ca852 --- /dev/null +++ b/docs/revm-python-spec/import_revm.py @@ -0,0 +1,121 @@ +""" +Import the Revm files. +""" + +import os + +# rm -Rf output folders +for folder in ["revm", "revm-coq", "spec", "spec-coq"]: + os.system(f"rm -Rf revm-verif/{folder}") + +crates_folder = "../../../../Rust/revm/crates" +spec_folder = "../../../../Ethereum/execution-specs/src/ethereum" +rust_coq_folder = "../../../../Rust/coq-of-rust/CoqOfRust/revm" +spec_coq_folder = "../../../../Ethereum/coq-of-python/CoqOfPython/ethereum" + +# For each Revm file, recursively import the file to the current directory. +for root, dirs, files in os.walk(crates_folder): + for file in files: + if file.endswith(".rs"): + file_path = os.path.join(root, file) + # Get the `root` path relative to `crates_folder`. + root_path = os.path.relpath(root, crates_folder) + new_file_path = os.path.join("revm-verif/revm", root_path, file[:-3] + ".md") + print(file_path) + print(new_file_path) + print() + with open(file_path, "r") as f: + # Create the directory if needed + os.makedirs(os.path.dirname(new_file_path), exist_ok=True) + with open(new_file_path, "w") as new_f: + new_f.write( + f"""# ๐Ÿฆ€ {file} + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/{root_path}/{file}) + +```rust +""" + + f.read() + + "```\n" + ) + +# For each Python spec file, recursively import the file to the current directory. +for root, dirs, files in os.walk(spec_folder): + for file in files: + if file.endswith(".py"): + file_path = os.path.join(root, file) + # Get the `root` path relative to `crates_folder`. + root_path = os.path.relpath(root, spec_folder) + new_file_path = os.path.join("revm-verif/spec", root_path, file[:-3] + ".md") + print(file_path) + print(new_file_path) + print() + with open(file_path, "r") as f: + # Create the directory if needed + os.makedirs(os.path.dirname(new_file_path), exist_ok=True) + with open(new_file_path, "w") as new_f: + new_f.write( + f"""# ๐Ÿ {file} + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/{root_path}/{file}) + +```python +""" + + f.read() + + "```\n" + ) + +for root, dirs, files in os.walk(rust_coq_folder): + for file in files: + if file.endswith(".v"): + file_path = os.path.join(root, file) + # Get the `root` path relative to `crates_folder`. + root_path = os.path.relpath(root, rust_coq_folder) + new_file_path = os.path.join("revm-verif/revm-coq", root_path, file[:-2] + ".md") + print(file_path) + print(new_file_path) + print() + with open(file_path, "r") as f: + # Create the directory if needed + os.makedirs(os.path.dirname(new_file_path), exist_ok=True) + with open(new_file_path, "w") as new_f: + new_f.write( + f"""# ๐Ÿ“ {file} + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/{root_path}/{file}) + +```coq +""" + + f.read() + + "```\n" + ) + +for root, dirs, files in os.walk(spec_coq_folder): + for file in files: + if file.endswith(".v"): + file_path = os.path.join(root, file) + # Get the `root` path relative to `crates_folder`. + root_path = os.path.relpath(root, spec_coq_folder) + new_file_path = \ + os.path.join( + "revm-verif/spec-coq", + root_path, + file[:-2] + ".md" + ) + print(file_path) + print(new_file_path) + print() + with open(file_path, "r") as f: + # Create the directory if needed + os.makedirs(os.path.dirname(new_file_path), exist_ok=True) + with open(new_file_path, "w") as new_f: + new_f.write( + f"""# ๐Ÿ“ {file} + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/{root_path}/{file}) + +```coq +""" + + f.read() + + "```\n" + ) diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/dependencies.md b/docs/revm-python-spec/revm-verif/revm-coq/links/dependencies.md new file mode 100644 index 00000000..c0fefdd3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/dependencies.md @@ -0,0 +1,51 @@ +# ๐Ÿ“ dependencies.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/dependencies.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. + +(* + /// Wrapper type around [`bytes::Bytes`] to support "0x" prefixed hex strings. + #[derive(Clone, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] + #[repr(transparent)] + pub struct Bytes(pub bytes::Bytes); +*) + +Module Bytes. + Parameter t : Set. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "bytes::bytes::Bytes"; + }. + + Global Instance IsToValue : ToValue t. + Admitted. +End Bytes. + +Module Address. + Parameter t : Set. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "alloy_primitives::bits::address::Address"; + }. + + Global Instance IsToValue : ToValue t. + Admitted. +End Address. + +Module FixedBytes. + Parameter t : Set. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + }. + + Global Instance IsToValue : ToValue t. + Admitted. +End FixedBytes. + +Definition B256 := FixedBytes.t. +Definition U256 := FixedBytes.t. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter.md new file mode 100644 index 00000000..84119cc9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter.md @@ -0,0 +1,103 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.revm.links.dependencies. +Require Import CoqOfRust.revm.links.interpreter.interpreter.instruction_result. +Require Import CoqOfRust.revm.links.interpreter.interpreter.gas. +Require Import CoqOfRust.revm.links.interpreter.interpreter.contract. +Require Import CoqOfRust.revm.links.interpreter.interpreter.shared_memory. +Require Import CoqOfRust.revm.links.interpreter.interpreter.stack. +Require Import CoqOfRust.revm.links.interpreter.interpreter.function_stack. +Require Import CoqOfRust.revm.links.interpreter.interpreter_action. + +(* + /// EVM bytecode interpreter. + #[derive(Debug)] + pub struct Interpreter { + /// The current instruction pointer. + pub instruction_pointer: *const u8, + /// The gas state. + pub gas: Gas, + /// Contract information and invoking data + pub contract: Contract, + /// The execution control flag. If this is not set to `Continue`, the interpreter will stop + /// execution. + pub instruction_result: InstructionResult, + /// Currently run Bytecode that instruction result will point to. + /// Bytecode is owned by the contract. + pub bytecode: Bytes, + /// Whether we are Interpreting the Ethereum Object Format (EOF) bytecode. + /// This is local field that is set from `contract.is_eof()`. + pub is_eof: bool, + /// Is init flag for eof create + pub is_eof_init: bool, + /// Shared memory. + /// + /// Note: This field is only set while running the interpreter loop. + /// Otherwise it is taken and replaced with empty shared memory. + pub shared_memory: SharedMemory, + /// Stack. + pub stack: Stack, + /// EOF function stack. + pub function_stack: FunctionStack, + /// The return data buffer for internal calls. + /// It has multi usage: + /// + /// * It contains the output bytes of call sub call. + /// * When this interpreter finishes execution it contains the output bytes of this contract. + pub return_data_buffer: Bytes, + /// Whether the interpreter is in "staticcall" mode, meaning no state changes can happen. + pub is_static: bool, + /// Actions that the EVM should do. + /// + /// Set inside CALL or CREATE instructions and RETURN or REVERT instructions. Additionally those instructions will set + /// InstructionResult to CallOrCreate/Return/Revert so we know the reason. + pub next_action: InterpreterAction, + } +*) + +Module Interpreter. + Record t : Set := { + instruction_pointer : Z; + gas : Gas.t; + contract : Contract.t; + instruction_result : InstructionResult.t; + Bytecode : Bytes.t; + IsEof : bool; + IsEofInit : bool; + SharedMemory : SharedMemory.t; + stack : Stack.t; + function_stack : FunctionStack.t; + return_data_buffer : Bytes.t; + is_static : bool; + next_action : InterpreterAction.t; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::Interpreter"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::interpreter::Interpreter" [ + ("instruction_pointer", ฯ† x.(instruction_pointer)); + ("gas", ฯ† x.(gas)); + ("contract", ฯ† x.(contract)); + ("instruction_result", ฯ† x.(instruction_result)); + ("Bytecode", ฯ† x.(Bytecode)); + ("IsEof", ฯ† x.(IsEof)); + ("IsEofInit", ฯ† x.(IsEofInit)); + ("SharedMemory", ฯ† x.(SharedMemory)); + ("stack", ฯ† x.(stack)); + ("function_stack", ฯ† x.(function_stack)); + ("return_data_buffer", ฯ† x.(return_data_buffer)); + ("is_static", ฯ† x.(is_static)); + ("next_action", ฯ† x.(next_action)) + ]; + }. +End Interpreter. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/contract.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/contract.md new file mode 100644 index 00000000..247a6f5f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/contract.md @@ -0,0 +1,59 @@ +# ๐Ÿ“ contract.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter/contract.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.core.links.option. +Require Import CoqOfRust.revm.links.dependencies. +Require Import CoqOfRust.revm.links.primitives.bytecode. + +(* + /// EVM contract information. + #[derive(Clone, Debug, Default)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct Contract { + /// Contracts data + pub input: Bytes, + /// Bytecode contains contract code, size of original code, analysis with gas block and jump table. + /// Note that current code is extended with push padding and STOP at end. + pub bytecode: Bytecode, + /// Bytecode hash for legacy. For EOF this would be None. + pub hash: Option, + /// Target address of the account. Storage of this address is going to be modified. + pub target_address: Address, + /// Caller of the EVM. + pub caller: Address, + /// Value send to contract from transaction or from CALL opcodes. + pub call_value: U256, + } +*) + +Module Contract. + Record t : Set := { + input : Bytes.t; + bytecode : Bytecode.t; + hash : option B256; + target_address : Address.t; + caller : Address.t; + call_value : Z; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::contract::Contract"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::interpreter::contract::Contract" [ + ("input", ฯ† x.(input)); + ("bytecode", ฯ† x.(bytecode)); + ("hash", ฯ† x.(hash)); + ("target_address", ฯ† x.(target_address)); + ("caller", ฯ† x.(caller)); + ("call_value", ฯ† x.(call_value)) + ]; + }. +End Contract. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/function_stack.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/function_stack.md new file mode 100644 index 00000000..0401371e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/function_stack.md @@ -0,0 +1,71 @@ +# ๐Ÿ“ function_stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter/function_stack.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.core.links.array. + +(* + /// Function return frame. + /// Needed information for returning from a function. + #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct FunctionReturnFrame { + /// The index of the code container that this frame is executing. + pub idx: usize, + /// The program counter where frame execution should continue. + pub pc: usize, + } +*) + +Module FunctionReturnFrame. + Record t : Set := { + idx : Z; + pc : Z; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::function_return_frame::FunctionReturnFrame"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::interpreter::function_return_frame::FunctionReturnFrame" [ + ("idx", ฯ† x.(idx)); + ("pc", ฯ† x.(pc)) + ]; + }. +End FunctionReturnFrame. + +(* + /// Function Stack + #[derive(Debug, Default)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct FunctionStack { + pub return_stack: Vec, + pub current_code_idx: usize, + } +*) + +(* TODO: Vectors? *) +Module FunctionStack. + Record t : Set := { + return_stack : list FunctionReturnFrame.t; + current_code_idx : Z; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::function_stack::FunctionStack"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::interpreter::function_stack::FunctionStack" [ + ("return_stack", ฯ† x.(return_stack)); + ("current_code_idx", ฯ† x.(current_code_idx)) + ]; + }. +End FunctionStack. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/gas.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/gas.md new file mode 100644 index 00000000..3e348a5b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/gas.md @@ -0,0 +1,310 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter/gas.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require core.links.clone. +Require Import revm.translations.interpreter.gas. + +Import Run. + +(* + /// Represents the state of gas during execution. + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct Gas { + /// The initial gas limit. This is constant throughout execution. + limit: u64, + /// The remaining gas. + remaining: u64, + /// Refunded gas. This is used only at the end of execution. + refunded: i64, + } +*) + +Module Gas. + Record t : Set := { + limit : Z; + remaining : Z; + refunded : Z; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::gas::Gas"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::gas::Gas" [ + ("limit", ฯ† x.(limit)); + ("remaining", ฯ† x.(remaining)); + ("refunded", ฯ† x.(refunded)) + ]; + }. + + + Module SubPointer. + Definition get_limit : SubPointer.Runner.t t Z := {| + SubPointer.Runner.index := + Pointer.Index.StructRecord "revm_interpreter::gas::Gas" "limit"; + SubPointer.Runner.projection x := Some x.(limit); + SubPointer.Runner.injection x y := Some (x <| limit := y |>); + |}. + + Lemma get_limit_is_valid : + SubPointer.Runner.Valid.t get_limit. + Proof. + hauto l: on. + Qed. + + Definition get_remaining : SubPointer.Runner.t t Z := {| + SubPointer.Runner.index := + Pointer.Index.StructRecord "revm_interpreter::gas::Gas" "remaining"; + SubPointer.Runner.projection x := Some x.(remaining); + SubPointer.Runner.injection x y := Some (x <| remaining := y |>); + |}. + + Lemma get_remaining_is_valid : + SubPointer.Runner.Valid.t get_remaining. + Proof. + hauto l: on. + Qed. + + Definition get_refunded : SubPointer.Runner.t t Z := {| + SubPointer.Runner.index := + Pointer.Index.StructRecord "revm_interpreter::gas::Gas" "refunded"; + SubPointer.Runner.projection x := Some x.(refunded); + SubPointer.Runner.injection x y := Some (x <| refunded := y |>); + |}. + + Lemma get_refunded_is_valid : + SubPointer.Runner.Valid.t get_refunded. + Proof. + hauto l: on. + Qed. + End SubPointer. +End Gas. + +Module Impl_Clone. + Definition run_impl : clone.Clone.RunImpl Gas.t (ฮฆ Gas.t). + Proof. + constructor. + { (* clone *) + eexists; split. + { eapply IsTraitMethod.Explicit. + { apply gas.Impl_core_clone_Clone_for_revm_interpreter_gas_Gas.Implements. } + { reflexivity. } + } + { intros. + run_symbolic. + } + } + Defined. +End Impl_Clone. + +Module Impl_revm_interpreter_gas_Gas. + Definition Self : Set := Gas.t. + + (* + pub const fn new(limit: u64) -> Self { + Self { + limit, + remaining: limit, + refunded: 0, + } + } + *) + Definition run_new (limit : Z) : + {{ + gas.Impl_revm_interpreter_gas_Gas.new [] [ฯ† limit] โ‡“ + fun (v : Self) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + now instantiate (1 := Gas.Build_t _ _ _). + Defined. + + (* + pub const fn new_spent(limit: u64) -> Self { + Self { + limit, + remaining: 0, + refunded: 0, + } + } + *) + Definition run_new_spent (limit : Z) : + {{ + gas.Impl_revm_interpreter_gas_Gas.new_spent [] [ฯ† limit] โ‡“ + fun (v : Self) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + now instantiate (1 := Gas.Build_t _ _ _). + Defined. + + (* + pub const fn limit(&self) -> u64 { + self.limit + } + *) + Definition run_limit (self : Ref.t Self) : + {{ + gas.Impl_revm_interpreter_gas_Gas.limit [] [ฯ† self] โ‡“ + fun (v : Z) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + run_sub_pointer Gas.SubPointer.get_limit_is_valid. + run_symbolic. + Defined. + + (* + pub const fn memory(&self) -> u64 { + 0 + } + *) + Definition run_memory (self : Ref.t Self) : + {{ + gas.Impl_revm_interpreter_gas_Gas.memory [] [ฯ† self] โ‡“ + fun (v : Z) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + Defined. + + (* + pub const fn refunded(&self) -> i64 { + self.refunded + } + *) + Definition run_refunded (self : Ref.t Self) : + {{ + gas.Impl_revm_interpreter_gas_Gas.refunded [] [ฯ† self] โ‡“ + fun (v : Z) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + run_sub_pointer Gas.SubPointer.get_refunded_is_valid. + run_symbolic. + Defined. + + (* + pub const fn spent(&self) -> u64 { + self.limit - self.remaining + } + *) + Definition run_spent (self : Ref.t Self) : + {{ + gas.Impl_revm_interpreter_gas_Gas.spent [] [ฯ† self] โ‡“ + fun (v : Z) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + run_sub_pointer Gas.SubPointer.get_limit_is_valid. + run_symbolic. + run_sub_pointer Gas.SubPointer.get_remaining_is_valid. + run_symbolic. + Defined. + + (* + pub const fn spend(&self) -> u64 { + self.spent() + } + *) + Definition run_spend (self : Ref.t Self) : + {{ + gas.Impl_revm_interpreter_gas_Gas.spend [] [ฯ† self] โ‡“ + fun (v : Z) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + eapply Run.CallPrimitiveGetAssociatedFunction. { + apply gas.Impl_revm_interpreter_gas_Gas.AssociatedFunction_spent. + } + run_symbolic. + eapply Run.CallClosure. { + apply run_spent. + } + intros; run_symbolic. + Defined. + + (* + pub const fn remaining(&self) -> u64 { + self.remaining + } + *) + Definition run_remaining (self : Ref.t Self) : + {{ + gas.Impl_revm_interpreter_gas_Gas.remaining [] [ฯ† self] โ‡“ + fun (v : Z) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + run_sub_pointer Gas.SubPointer.get_remaining_is_valid. + run_symbolic. + Defined. + + (* + pub fn erase_cost(&mut self, returned: u64) { + self.remaining += returned; + } + *) + Definition run_erase_cost (self : Ref.t Self) (returned : Z) : + {{ + gas.Impl_revm_interpreter_gas_Gas.erase_cost [] [ฯ† self; ฯ† returned] โ‡“ + fun (v : unit) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + run_sub_pointer Gas.SubPointer.get_remaining_is_valid. + run_symbolic. + eapply Run.Let. { + run_symbolic. + } + intros; run_symbolic. + Defined. + + (* + pub fn spend_all(&mut self) { + self.remaining = 0; + } + *) + Definition run_spend_all (self : Ref.t Self) : + {{ + gas.Impl_revm_interpreter_gas_Gas.spend_all [] [ฯ† self] โ‡“ + fun (v : unit) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + eapply Run.Let. { + run_symbolic. + run_sub_pointer Gas.SubPointer.get_remaining_is_valid. + run_symbolic. + } + intros; run_symbolic. + Defined. + + (* + pub fn record_refund(&mut self, refund: i64) { + self.refunded += refund; + } + *) + Definition run_record_refund (self : Ref.t Self) (refund : Z) : + {{ + gas.Impl_revm_interpreter_gas_Gas.record_refund [] [ฯ† self; ฯ† refund] โ‡“ + fun (v : unit) => inl (ฯ† v) + }}. + Proof. + run_symbolic. + run_sub_pointer Gas.SubPointer.get_refunded_is_valid. + run_symbolic. + eapply Run.Let. { + run_symbolic. + } + intros; run_symbolic. + Defined. +End Impl_revm_interpreter_gas_Gas. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/instruction_result.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/instruction_result.md new file mode 100644 index 00000000..2d7a78f6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/instruction_result.md @@ -0,0 +1,151 @@ +# ๐Ÿ“ instruction_result.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter/instruction_result.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. + +(* + #[repr(u8)] + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub enum InstructionResult { + // success codes + #[default] + Continue = 0x00, + Stop, + Return, + SelfDestruct, + ReturnContract, + + // revert codes + Revert = 0x10, // revert opcode + CallTooDeep, + OutOfFunds, + + // Actions + CallOrCreate = 0x20, + + // error codes + OutOfGas = 0x50, + MemoryOOG, + MemoryLimitOOG, + PrecompileOOG, + InvalidOperandOOG, + OpcodeNotFound, + CallNotAllowedInsideStatic, + StateChangeDuringStaticCall, + InvalidFEOpcode, + InvalidJump, + NotActivated, + StackUnderflow, + StackOverflow, + OutOfOffset, + CreateCollision, + OverflowPayment, + PrecompileError, + NonceOverflow, + /// Create init code size exceeds limit (runtime). + CreateContractSizeLimit, + /// Error on created contract that begins with EF + CreateContractStartingWithEF, + /// EIP-3860: Limit and meter initcode. Initcode size limit exceeded. + CreateInitCodeSizeLimit, + /// Fatal external error. Returned by database. + FatalExternalError, + /// RETURNCONTRACT called in not init eof code. + ReturnContractInNotInitEOF, + /// Legacy contract is calling opcode that is enabled only in EOF. + EOFOpcodeDisabledInLegacy, + /// EOF function stack overflow + EOFFunctionStackOverflow, + } +*) + +Module InstructionResult. + Inductive t : Set := + (* success codes *) + | Continue + | Stop + | Return + | SelfDestruct + | ReturnContract + (* revert codes *) + | Revert + | CallTooDeep + | OutOfFunds + (* Actions *) + | CallOrCreate + (* error codes *) + | OutOfGas + | MemoryOOG + | MemoryLimitOOG + | PrecompileOOG + | InvalidOperandOOG + | OpcodeNotFound + | CallNotAllowedInsideStatic + | StateChangeDuringStaticCall + | InvalidFEOpcode + | InvalidJump + | NotActivated + | StackUnderflow + | StackOverflow + | OutOfOffset + | CreateCollision + | OverflowPayment + | PrecompileError + | NonceOverflow + | CreateContractSizeLimit + | CreateContractStartingWithEF + | CreateInitCodeSizeLimit + | FatalExternalError + | ReturnContractInNotInitEOF + | EOFOpcodeDisabledInLegacy + | EOFFunctionStackOverflow. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::instruction_result::InstructionResult"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + match x with + | Continue => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::Continue" [] + | Stop => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::Stop" [] + | Return => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::Return" [] + | SelfDestruct => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" [] + | ReturnContract => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::ReturnContract" [] + | Revert => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::Revert" [] + | CallTooDeep => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" [] + | OutOfFunds => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" [] + | CallOrCreate => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" [] + | OutOfGas => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::OutOfGas" [] + | MemoryOOG => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" [] + | MemoryLimitOOG => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::MemoryLimitOOG" [] + | PrecompileOOG => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::PrecompileOOG" [] + | InvalidOperandOOG => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" [] + | OpcodeNotFound => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::OpcodeNotFound" [] + | CallNotAllowedInsideStatic => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::CallNotAllowedInsideStatic" [] + | StateChangeDuringStaticCall => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" [] + | InvalidFEOpcode => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::InvalidFEOpcode" [] + | InvalidJump => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::InvalidJump" [] + | NotActivated => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::NotActivated" [] + | StackUnderflow => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" [] + | StackOverflow => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::StackOverflow" [] + | OutOfOffset => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::OutOfOffset" [] + | CreateCollision => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::CreateCollision" [] + | OverflowPayment => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::OverflowPayment" [] + | PrecompileError => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::PrecompileError" [] + | NonceOverflow => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::NonceOverflow" [] + | CreateContractSizeLimit => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::CreateContractSizeLimit" [] + | CreateContractStartingWithEF => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::CreateContractStartingWithEF" [] + | CreateInitCodeSizeLimit => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::CreateInitCodeSizeLimit" [] + | FatalExternalError => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::FatalExternalError" [] + | ReturnContractInNotInitEOF => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::ReturnContractInNotInitEOF" [] + | EOFOpcodeDisabledInLegacy => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" [] + | EOFFunctionStackOverflow => Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::EOFFunctionStackOverflow" [] + end; + }. +End InstructionResult. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/shared_memory.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/shared_memory.md new file mode 100644 index 00000000..3eb6eb2f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/shared_memory.md @@ -0,0 +1,54 @@ +# ๐Ÿ“ shared_memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter/shared_memory.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.core.links.option. +Require Import CoqOfRust.core.links.array. + +(* + /// A sequential memory shared between calls, which uses + /// a `Vec` for internal representation. + /// A [SharedMemory] instance should always be obtained using + /// the `new` static method to ensure memory safety. + #[derive(Clone, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct SharedMemory { + /// The underlying buffer. + buffer: Vec, + /// Memory checkpoints for each depth. + /// Invariant: these are always in bounds of `data`. + checkpoints: Vec, + /// Invariant: equals `self.checkpoints.last()` + last_checkpoint: usize, + /// Memory limit. See [`CfgEnv`](revm_primitives::CfgEnv). + #[cfg(feature = "memory_limit")] + memory_limit: u64, + } +*) + +Module SharedMemory. + Record t : Set := { + buffer : list Z; + checkpoints : list Z; + last_checkpoint : Z; + memory_limit : option Z; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::interpreter::shared_memory::SharedMemory" [ + ("buffer", ฯ† x.(buffer)); + ("checkpoints", ฯ† x.(checkpoints)); + ("last_checkpoint", ฯ† x.(last_checkpoint)); + ("memory_limit", ฯ† x.(memory_limit)) + ]; + }. +End SharedMemory. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/stack.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/stack.md new file mode 100644 index 00000000..ae493b2d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter/stack.md @@ -0,0 +1,34 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter/stack.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.core.links.array. +Require Import CoqOfRust.revm.links.dependencies. + +(* + /// EVM stack with [STACK_LIMIT] capacity of words. + #[derive(Debug, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize))] + pub struct Stack { + /// The underlying data of the stack. + data: Vec, + } +*) + +Module Stack. + Inductive t : Set := + | data : list U256 -> t. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::stack::Stack"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† '(data x) := + Value.StructRecord "revm_interpreter::interpreter::stack::Stack" [("data", ฯ† x)] + }. +End Stack. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action.md new file mode 100644 index 00000000..39b7aeed --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action.md @@ -0,0 +1,93 @@ +# ๐Ÿ“ interpreter_action.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter_action.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.revm.links.dependencies. +Require Import CoqOfRust.revm.links.interpreter.interpreter_action.call_inputs. +Require Import CoqOfRust.revm.links.interpreter.interpreter_action.create_inputs. +Require Import CoqOfRust.revm.links.interpreter.interpreter_action.eof_create_inputs. +Require Import CoqOfRust.revm.links.interpreter.interpreter.instruction_result. +Require Import CoqOfRust.revm.links.interpreter.interpreter.gas. + +(* + /// The result of an interpreter operation. + #[derive(Clone, Debug, PartialEq, Eq)] + #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] + pub struct InterpreterResult { + /// The result of the instruction execution. + pub result: InstructionResult, + /// The output of the instruction execution. + pub output: Bytes, + /// The gas usage information. + pub gas: Gas, + } +*) + +Module InterpreterResult. + Record t : Set := { + result : InstructionResult.t; + output : Bytes.t; + gas : Gas.t; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::InterpreterResult"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::interpreter::InterpreterResult" [ + ("result", ฯ† x.(result)); + ("output", ฯ† x.(output)); + ("gas", ฯ† x.(gas)) + ]; + }. +End InterpreterResult. + +(* + #[derive(Clone, Debug, Default, PartialEq, Eq)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub enum InterpreterAction { + /// CALL, CALLCODE, DELEGATECALL, STATICCALL + /// or EOF EXT instuction called. + Call { inputs: Box }, + /// CREATE or CREATE2 instruction called. + Create { inputs: Box }, + /// EOF CREATE instruction called. + EOFCreate { inputs: Box }, + /// Interpreter finished execution. + Return { result: InterpreterResult }, + /// No action + #[default] + None, + } +*) + +(* TODO: Box? *) +Module InterpreterAction. + Inductive t : Set := + | Call : CallInputs.t -> t + | Create : CreateInputs.t -> t + | EOFCreate : EOFCreateInput.t -> t + | Return : InterpreterResult.t -> t + | None. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter_action::InterpreterAction"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + match x with + | Call x => Value.StructRecord "revm_interpreter::interpreter_action::InterpreterAction::Call" [("inputs", ฯ† x)] + | Create x => Value.StructRecord "revm_interpreter::interpreter_action::InterpreterAction::Create" [("inputs", ฯ† x)] + | EOFCreate x => Value.StructRecord "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate" [("inputs", ฯ† x)] + | Return x => Value.StructRecord "revm_interpreter::interpreter_action::InterpreterAction::Return" [("result", ฯ† x)] + | None => Value.StructRecord "revm_interpreter::interpreter_action::InterpreterAction::None" [] + end; + }. +End InterpreterAction. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/call_inputs.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/call_inputs.md new file mode 100644 index 00000000..f26bee5d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/call_inputs.md @@ -0,0 +1,159 @@ +# ๐Ÿ“ call_inputs.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter_action/call_inputs.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.core.links.bool. +Require Import CoqOfRust.revm.links.dependencies. + +(* + /// Call value. + #[derive(Clone, Debug, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub enum CallValue { + /// Concrete value, transferred from caller to callee at the end of the transaction. + Transfer(U256), + /// Apparent value, that is **not** actually transferred. + /// + /// Set when in a `DELEGATECALL` call type, and used by the `CALLVALUE` opcode. + Apparent(U256), + } +*) + +Module CallValue. + Inductive t : Set := + | Transfer : Z -> t + | Apparent : Z -> t. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + match x with + | Transfer x => Value.StructTuple "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer" [ฯ† x] + | Apparent x => Value.StructTuple "revm_interpreter::interpreter_action::call_inputs::CallValue::Approval" [ฯ† x] + end; + }. +End CallValue. + +(* + /// Call scheme. + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub enum CallScheme { + /// `CALL`. + Call, + /// `CALLCODE` + CallCode, + /// `DELEGATECALL` + DelegateCall, + /// `STATICCALL` + StaticCall, + } +*) + +Module CallScheme. + Inductive t : Set := + | Call + | CallCode + | DelegateCall + | StaticCall. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + match x with + | Call => Value.StructTuple "revm_interpreter::interpreter_action::call_inputs::CallScheme::Call" [] + | CallCode => Value.StructTuple "revm_interpreter::interpreter_action::call_inputs::CallScheme::CallCode" [] + | DelegateCall => Value.StructTuple "revm_interpreter::interpreter_action::call_inputs::CallScheme::DelegateCall" [] + | StaticCall => Value.StructTuple "revm_interpreter::interpreter_action::call_inputs::CallScheme::StaticCall" [] + end; + }. +End CallScheme. + + +(* + /// Inputs for a call. + #[derive(Clone, Debug, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct CallInputs { + /// The call data of the call. + pub input: Bytes, + /// The return memory offset where the output of the call is written. + /// + /// In EOF, this range is invalid as EOF calls do not write output to memory. + pub return_memory_offset: Range, + /// The gas limit of the call. + pub gas_limit: u64, + /// The account address of bytecode that is going to be executed. + /// + /// Previously `context.code_address`. + pub bytecode_address: Address, + /// Target address, this account storage is going to be modified. + /// + /// Previously `context.address`. + pub target_address: Address, + /// This caller is invoking the call. + /// + /// Previously `context.caller`. + pub caller: Address, + /// Call value. + /// + /// NOTE: This value may not necessarily be transferred from caller to callee, see [`CallValue`]. + /// + /// Previously `transfer.value` or `context.apparent_value`. + pub value: CallValue, + /// The call scheme. + /// + /// Previously `context.scheme`. + pub scheme: CallScheme, + /// Whether the call is a static call, or is initiated inside a static call. + pub is_static: bool, + /// Whether the call is initiated from EOF bytecode. + pub is_eof: bool, + } +*) + +(* TODO: Ranges? *) +Module CallInputs. + Record t : Set := { + input : Bytes.t; + return_memory_offset : (Z * Z); + gas_limit : Z; + bytecode_address : Address.t; + target_address : Address.t; + caller : Address.t; + value : CallValue.t; + scheme : CallScheme.t; + is_static : bool; + is_eof : bool; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::call_inputs::CallInputs"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::interpreter::call_inputs::CallInputs" [ + ("input", ฯ† x.(input)); + ("return_memory_offset", ฯ† x.(return_memory_offset)); + ("gas_limit", ฯ† x.(gas_limit)); + ("bytecode_address", ฯ† x.(bytecode_address)); + ("target_address", ฯ† x.(target_address)); + ("caller", ฯ† x.(caller)); + ("value", ฯ† x.(value)); + ("scheme", ฯ† x.(scheme)); + ("is_static", ฯ† x.(is_static)); + ("is_eof", ฯ† x.(is_eof)) + ]; + }. +End CallInputs. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/create_inputs.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/create_inputs.md new file mode 100644 index 00000000..ba916611 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/create_inputs.md @@ -0,0 +1,53 @@ +# ๐Ÿ“ create_inputs.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter_action/create_inputs.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.revm.links.dependencies. +Require Import CoqOfRust.revm.links.primitives.env. + +(* + /// Inputs for a create call. + #[derive(Clone, Debug, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct CreateInputs { + /// Caller address of the EVM. + pub caller: Address, + /// The create scheme. + pub scheme: CreateScheme, + /// The value to transfer. + pub value: U256, + /// The init code of the contract. + pub init_code: Bytes, + /// The gas limit of the call. + pub gas_limit: u64, + } +*) + +Module CreateInputs. + Record t : Set := { + caller : Address.t; + scheme : CreateScheme.t; + value : U256; + init_code : Bytes.t; + gas_limit : Z; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::create_inputs::CreateInputs"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::interpreter::create_inputs::CreateInputs" [ + ("caller", ฯ† x.(caller)); + ("scheme", ฯ† x.(scheme)); + ("value", ฯ† x.(value)); + ("init_code", ฯ† x.(init_code)); + ("gas_limit", ฯ† x.(gas_limit)) + ]; + }. +End CreateInputs. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/eof_create_inputs.md b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/eof_create_inputs.md new file mode 100644 index 00000000..297c47c8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/interpreter/interpreter_action/eof_create_inputs.md @@ -0,0 +1,58 @@ +# ๐Ÿ“ eof_create_inputs.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/interpreter/interpreter_action/eof_create_inputs.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.revm.links.dependencies. +Require Import CoqOfRust.revm.links.primitives.bytecode.eof. + +(* + /// Inputs for EOF create call. + #[derive(Debug, Default, Clone, PartialEq, Eq)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct EOFCreateInput { + /// Caller of Eof Craate + pub caller: Address, + /// New contract address. + pub created_address: Address, + /// Values of ether transfered + pub value: U256, + /// Init eof code that is going to be executed. + pub eof_init_code: Eof, + /// Gas limit for the create call. + pub gas_limit: u64, + /// Return memory range. If EOF creation Reverts it can return the + /// the memory range. + pub return_memory_range: Range, + } +*) + +Module EOFCreateInput. + Record t : Set := { + caller : Address.t; + created_address : Address.t; + value : U256; + eof_init_code : Eof.t; + gas_limit : Z; + return_memory_range : (Z * Z); + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_interpreter::interpreter::eof_create_input::EOFCreateInput"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_interpreter::interpreter::eof_create_input::EOFCreateInput" [ + ("caller", ฯ† x.(caller)); + ("created_address", ฯ† x.(created_address)); + ("value", ฯ† x.(value)); + ("eof_init_code", ฯ† x.(eof_init_code)); + ("gas_limit", ฯ† x.(gas_limit)); + ("return_memory_range", ฯ† x.(return_memory_range)) + ]; + }. +End EOFCreateInput. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode.md b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode.md new file mode 100644 index 00000000..4225d889 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode.md @@ -0,0 +1,33 @@ +# ๐Ÿ“ bytecode.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/primitives/bytecode.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. + +(* + /// State of the [`Bytecode`] analysis. + #[derive(Clone, Debug, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub enum Bytecode { + /// No analysis has been performed. + LegacyRaw(Bytes), + /// The bytecode has been analyzed for valid jump destinations. + LegacyAnalyzed(LegacyAnalyzedBytecode), + /// Ethereum Object Format + Eof(Eof), + } +*) + +Module Bytecode. + Parameter t : Set. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_primitives::bytecode::Bytecode"; + }. + + Global Instance IsToValue : ToValue t. + Admitted. +End Bytecode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof.md b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof.md new file mode 100644 index 00000000..aa4e072f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof.md @@ -0,0 +1,49 @@ +# ๐Ÿ“ eof.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/primitives/bytecode/eof.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.revm.links.dependencies. +Require Import CoqOfRust.revm.links.primitives.bytecode.eof.header. +Require Import CoqOfRust.revm.links.primitives.bytecode.eof.body. + +(* + /// EOF - Ethereum Object Format. + /// + /// It consist of a header, body and raw original bytes Specified in EIP. + /// Most of body contain Bytes so it references to the raw bytes. + /// + /// If there is a need to create new EOF from scratch, it is recommended to use `EofBody` and + /// use `encode` function to create full [`Eof`] object. + #[derive(Clone, Debug, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct Eof { + pub header: EofHeader, + pub body: EofBody, + pub raw: Bytes, + } +*) + +Module Eof. + Record t : Set := { + header : EofHeader.t; + body : EofBody.t; + raw : Bytes.t; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_primitives::bytecode::eof::Eof"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_primitives::bytecode::eof::Eof" [ + ("header", ฯ† x.(header)); + ("body", ฯ† x.(body)); + ("raw", ฯ† x.(raw)) + ]; + }. +End Eof. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/body.md b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/body.md new file mode 100644 index 00000000..63a1c2cc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/body.md @@ -0,0 +1,52 @@ +# ๐Ÿ“ body.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/primitives/bytecode/eof/body.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.core.links.bool. +Require Import CoqOfRust.core.links.array. +Require Import CoqOfRust.revm.links.dependencies. +Require Import CoqOfRust.revm.links.primitives.bytecode.eof.type_section. + +(* + /// EOF Body, contains types, code, container and data sections. + /// + /// Can be used to create new EOF object. + #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct EofBody { + pub types_section: Vec, + pub code_section: Vec, + pub container_section: Vec, + pub data_section: Bytes, + pub is_data_filled: bool, + } +*) + +Module EofBody. + Record t : Set := { + types_section : list TypesSection.t; + code_section : list Bytes.t; + container_section : list Bytes.t; + data_section : Bytes.t; + is_data_filled : bool; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_primitives::bytecode::eof::body::EofBody"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_primitives::bytecode::eof::body::EofBody" [ + ("types_section", ฯ† x.(types_section)); + ("code_section", ฯ† x.(code_section)); + ("container_section", ฯ† x.(container_section)); + ("data_section", ฯ† x.(data_section)); + ("is_data_filled", ฯ† x.(is_data_filled)) + ]; + }. +End EofBody. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/header.md b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/header.md new file mode 100644 index 00000000..44c66a54 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/header.md @@ -0,0 +1,59 @@ +# ๐Ÿ“ header.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/primitives/bytecode/eof/header.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.core.links.array. + +(* + /// EOF Header containing + #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct EofHeader { + /// Size of EOF types section. + /// types section includes num of input and outputs and max stack size. + pub types_size: u16, + /// Sizes of EOF code section. + /// Code size can't be zero. + pub code_sizes: Vec, + /// EOF Container size. + /// Container size can be zero. + pub container_sizes: Vec, + /// EOF data size. + pub data_size: u16, + /// sum code sizes + pub sum_code_sizes: usize, + /// sum container sizes + pub sum_container_sizes: usize, + } +*) + +Module EofHeader. + Record t : Set := { + types_size : Z; + code_sizes : list Z; + container_sizes : list Z; + data_size : Z; + sum_code_sizes : Z; + sum_container_sizes : Z; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_primitives::bytecode::eof::header::EofHeader"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_primitives::bytecode::eof::header::EofHeader" [ + ("types_size", ฯ† x.(types_size)); + ("code_sizes", ฯ† x.(code_sizes)); + ("container_sizes", ฯ† x.(container_sizes)); + ("data_size", ฯ† x.(data_size)); + ("sum_code_sizes", ฯ† x.(sum_code_sizes)); + ("sum_container_sizes", ฯ† x.(sum_container_sizes)) + ]; + }. +End EofHeader. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/type_section.md b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/type_section.md new file mode 100644 index 00000000..40723bf2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/bytecode/eof/type_section.md @@ -0,0 +1,47 @@ +# ๐Ÿ“ type_section.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/primitives/bytecode/eof/type_section.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. + + +(* + /// Types section that contains stack information for matching code section. + #[derive(Debug, Clone, Default, Hash, PartialEq, Eq, Copy)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct TypesSection { + /// inputs - 1 byte - `0x00-0x7F` + /// number of stack elements the code section consumes + pub inputs: u8, + /// outputs - 1 byte - `0x00-0x80` + /// number of stack elements the code section returns or 0x80 for non-returning functions + pub outputs: u8, + /// max_stack_height - 2 bytes - `0x0000-0x03FF` + /// maximum number of elements ever placed onto the stack by the code section + pub max_stack_size: u16, + } +*) + +Module TypesSection. + Record t : Set := { + inputs : Z; + outputs : Z; + max_stack_size : Z; + }. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + Value.StructRecord "revm_primitives::bytecode::eof::types_section::TypesSection" [ + ("inputs", ฯ† x.(inputs)); + ("outputs", ฯ† x.(outputs)); + ("max_stack_size", ฯ† x.(max_stack_size)) + ]; + }. +End TypesSection. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/env.md b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/env.md new file mode 100644 index 00000000..fc8caf71 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/links/primitives/env.md @@ -0,0 +1,41 @@ +# ๐Ÿ“ env.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/links/primitives/env.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. + +(* + /// Create scheme. + #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub enum CreateScheme { + /// Legacy create scheme of `CREATE`. + Create, + /// Create scheme of `CREATE2`. + Create2 { + /// Salt. + salt: U256, + }, + } +*) + +Module CreateScheme. + Inductive t : Set := + | Create + | Create2 : Z -> t. + + Global Instance IsToTy : ToTy t := { + ฮฆ := Ty.path "revm_primitives::env::CreateScheme"; + }. + + Global Instance IsToValue : ToValue t := { + ฯ† x := + match x with + | Create => Value.StructTuple "revm_primitives::env::CreateScheme::Create" [] + | Create2 x => Value.StructTuple "revm_primitives::env::CreateScheme::Create2" [ฯ† x] + end; + }. +End CreateScheme. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/instructions/macros.md b/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/instructions/macros.md new file mode 100644 index 00000000..89eabda9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/instructions/macros.md @@ -0,0 +1,45 @@ +# ๐Ÿ“ macros.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/simulations/interpreter/instructions/macros.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.simulations.M. +Import simulations.M.Notations. +Require Import CoqOfRust.revm.links.interpreter.interpreter. +Require Import CoqOfRust.revm.links.interpreter.interpreter.gas. +Require Import CoqOfRust.revm.links.interpreter.interpreter.instruction_result. +Require Import CoqOfRust.revm.simulations.interpreter.interpreter. +Require Import CoqOfRust.revm.simulations.interpreter.interpreter.gas. + + +(* + /// Records a `gas` cost and fails the instruction if it would exceed the available gas. + #[macro_export] + macro_rules! gas { + ($interp:expr, $gas:expr) => { + $crate::gas!($interp, $gas, ()) + }; + ($interp:expr, $gas:expr, $ret:expr) => { + if !$interp.gas.record_cost($gas) { + $interp.instruction_result = $crate::InstructionResult::OutOfGas; + return $ret; + } + }; + } +*) + +Definition gas_macro (gas : Z) : + MS? Interpreter.t string unit := + letS? interp := readS? in + letS? success := liftS? Interpreter.Lens.gas (Gas.record_cost gas) in + if negb success + then + letS? _ := writeS? (interp <| + Interpreter.instruction_result := InstructionResult.OutOfGas + |>) in + returnS? tt + else + returnS? tt. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter.md b/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter.md new file mode 100644 index 00000000..e50e97f8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter.md @@ -0,0 +1,28 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/simulations/interpreter/interpreter.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.simulations.M. +Import simulations.M.Notations. +Require Import CoqOfRust.revm.links.dependencies. +Require Import CoqOfRust.revm.links.interpreter.interpreter.instruction_result. +Require Import CoqOfRust.revm.links.interpreter.interpreter.gas. +Require Import CoqOfRust.revm.links.interpreter.interpreter.contract. +Require Import CoqOfRust.revm.links.interpreter.interpreter.shared_memory. +Require Import CoqOfRust.revm.links.interpreter.interpreter.stack. +Require Import CoqOfRust.revm.links.interpreter.interpreter.function_stack. +Require Import CoqOfRust.revm.links.interpreter.interpreter_action. +Require Import CoqOfRust.revm.links.interpreter.interpreter. + +Module Interpreter. + Module Lens. + Definition gas : Lens.t Interpreter.t Gas.t := {| + Lens.read interp := Interpreter.gas interp; + Lens.write interp gas := interp <| Interpreter.gas := gas |> + |}. + End Lens. +End Interpreter. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter/gas.md b/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter/gas.md new file mode 100644 index 00000000..21c33658 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter/gas.md @@ -0,0 +1,41 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/simulations/interpreter/interpreter/gas.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.simulations.M. +Import simulations.M.Notations. +Require Import CoqOfRust.revm.links.interpreter.interpreter.gas. + +Module Gas. + (* + /// Records an explicit cost. + /// + /// Returns `false` if the gas limit is exceeded. + #[inline] + #[must_use = "prefer using `gas!` instead to return an out-of-gas error on failure"] + pub fn record_cost(&mut self, cost: u64) -> bool { + let (remaining, overflow) = self.remaining.overflowing_sub(cost); + let success = !overflow; + if success { + self.remaining = remaining; + } + success + } + *) + Definition record_cost + (cost : Z) : + MS? Gas.t string bool := + letS? 'gas := readS? in + let remaining_sub_cost := gas.(Gas.remaining) - cost in + let success := remaining_sub_cost >=? 0 in + letS? _ := + if success + then writeS? (gas <| Gas.remaining := remaining_sub_cost |>) + else returnS? tt + in + returnS? success. +End Gas. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter/stack.md b/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter/stack.md new file mode 100644 index 00000000..54b0931c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/simulations/interpreter/interpreter/stack.md @@ -0,0 +1,124 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/simulations/interpreter/interpreter/stack.v) + +```coq +Require Import CoqOfRust.CoqOfRust. +Require Import CoqOfRust.links.M. +Require Import CoqOfRust.simulations.M. +Import simulations.M.Notations. +Require Import CoqOfRust.core.links.array. +Require Import CoqOfRust.revm.links.dependencies. +Require Import CoqOfRust.revm.links.interpreter.interpreter.instruction_result. +Require Import CoqOfRust.revm.links.interpreter.interpreter.stack. + +Module Stack. + (* + /// Returns the length of the stack in words. + #[inline] + pub fn len(&self) -> usize { + self.data.len() + } + *) + Definition len '(Stack.data stack) : Z := + Z.of_nat (List.length stack). + + (* + /// Removes the topmost element from the stack and returns it, or `StackUnderflow` if it is + /// empty. + #[inline] + pub fn pop(&mut self) -> Result { + self.data.pop().ok_or(InstructionResult::StackUnderflow) + } + *) + Definition pop : + MS? Stack.t string (U256 + InstructionResult.t) := + letS? '(Stack.data stack) := readS? in + match stack with + | [] => returnS? (inr InstructionResult.StackUnderflow) + | x :: xs => + letS? _ := writeS? (Stack.data xs) in + returnS? (inl x) + end. + + (* + /// Removes the topmost element from the stack and returns it. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop_unsafe(&mut self) -> U256 { + self.data.pop().unwrap_unchecked() + } + *) + Definition pop_unsafe : + MS? Stack.t string U256 := + letS? result := pop in + match result with + | inl x => returnS? x + | inr _ => panicS? "Stack underflow" + end. + + (* + /// Peeks the top of the stack. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn top_unsafe(&mut self) -> &mut U256 { + let len = self.data.len(); + self.data.get_unchecked_mut(len - 1) + } + *) + Definition top_unsafe : + MS? Stack.t string U256 := + letS? '(Stack.data stack) := readS? in + match stack with + | [] => panicS? "Stack underflow" + | x :: _ => returnS? x + end. + + (* + /// Pop the topmost value, returning the value and the new topmost value. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop_top_unsafe(&mut self) -> (U256, &mut U256) { + let pop = self.pop_unsafe(); + let top = self.top_unsafe(); + (pop, top) + } + *) + Definition pop_top_unsafe : + MS? Stack.t string (U256 * U256) := + letS? pop := pop_unsafe in + letS? top := top_unsafe in + returnS? (pop, top). + + (* + /// Pops 2 values from the stack and returns them, in addition to the new topmost value. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop2_top_unsafe(&mut self) -> (U256, U256, &mut U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + let top = self.top_unsafe(); + + (pop1, pop2, top) + } + *) + Definition pop2_top_unsafe : + MS? Stack.t string (U256 * U256 * U256) := + letS? pop1 := pop_unsafe in + letS? pop2 := pop_unsafe in + letS? top := top_unsafe in + returnS? (pop1, pop2, top). +End Stack. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/function_stack.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/function_stack.md new file mode 100644 index 00000000..ae3dfbad --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/function_stack.md @@ -0,0 +1,700 @@ +# ๐Ÿ“ function_stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/function_stack.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module function_stack. + (* StructRecord + { + name := "FunctionReturnFrame"; + ty_params := []; + fields := [ ("idx", Ty.path "usize"); ("pc", Ty.path "usize") ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "FunctionReturnFrame" |); + M.read (| Value.String "idx" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionReturnFrame", + "idx" + |)); + M.read (| Value.String "pc" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionReturnFrame", + "pc" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_function_stack_FunctionReturnFrame. + + Module Impl_core_default_Default_for_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::function_stack::FunctionReturnFrame" + [ + ("idx", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "usize", + [], + "default", + [] + |), + [] + |)); + ("pc", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "usize", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_function_stack_FunctionReturnFrame. + + Module Impl_core_clone_Clone_for_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_function_stack_FunctionReturnFrame. + + Module Impl_core_marker_Copy_for_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_function_stack_FunctionReturnFrame. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_function_stack_FunctionReturnFrame. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionReturnFrame", + "idx" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::function_stack::FunctionReturnFrame", + "idx" + |) + |)), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionReturnFrame", + "pc" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::function_stack::FunctionReturnFrame", + "pc" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_function_stack_FunctionReturnFrame. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_function_stack_FunctionReturnFrame. + + Module Impl_core_cmp_Eq_for_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_function_stack_FunctionReturnFrame. + + Module Impl_core_hash_Hash_for_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "usize", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionReturnFrame", + "idx" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "usize", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionReturnFrame", + "pc" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_function_stack_FunctionReturnFrame. + + Module Impl_revm_interpreter_function_stack_FunctionReturnFrame. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionReturnFrame". + + (* + pub fn new(idx: usize, pc: usize) -> Self { + Self { idx, pc } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ idx; pc ] => + ltac:(M.monadic + (let idx := M.alloc (| idx |) in + let pc := M.alloc (| pc |) in + Value.StructRecord + "revm_interpreter::function_stack::FunctionReturnFrame" + [ ("idx", M.read (| idx |)); ("pc", M.read (| pc |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + End Impl_revm_interpreter_function_stack_FunctionReturnFrame. + + (* StructRecord + { + name := "FunctionStack"; + ty_params := []; + fields := + [ + ("return_stack", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_interpreter::function_stack::FunctionReturnFrame"; + Ty.path "alloc::alloc::Global" + ]); + ("current_code_idx", Ty.path "usize") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_function_stack_FunctionStack. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionStack". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "FunctionStack" |); + M.read (| Value.String "return_stack" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionStack", + "return_stack" + |)); + M.read (| Value.String "current_code_idx" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionStack", + "current_code_idx" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_function_stack_FunctionStack. + + Module Impl_core_default_Default_for_revm_interpreter_function_stack_FunctionStack. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionStack". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::function_stack::FunctionStack" + [ + ("return_stack", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_interpreter::function_stack::FunctionReturnFrame"; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)); + ("current_code_idx", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "usize", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_function_stack_FunctionStack. + + Module Impl_revm_interpreter_function_stack_FunctionStack. + Definition Self : Ty.t := Ty.path "revm_interpreter::function_stack::FunctionStack". + + (* + pub fn new() -> Self { + Self { + return_stack: Vec::new(), + current_code_idx: 0, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::function_stack::FunctionStack" + [ + ("return_stack", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_interpreter::function_stack::FunctionReturnFrame"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |)); + ("current_code_idx", Value.Integer 0) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn push(&mut self, program_counter: usize, new_idx: usize) { + self.return_stack.push(FunctionReturnFrame { + idx: self.current_code_idx, + pc: program_counter, + }); + self.current_code_idx = new_idx; + } + *) + Definition push (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; program_counter; new_idx ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let program_counter := M.alloc (| program_counter |) in + let new_idx := M.alloc (| new_idx |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_interpreter::function_stack::FunctionReturnFrame"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionStack", + "return_stack" + |); + Value.StructRecord + "revm_interpreter::function_stack::FunctionReturnFrame" + [ + ("idx", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionStack", + "current_code_idx" + |) + |)); + ("pc", M.read (| program_counter |)) + ] + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionStack", + "current_code_idx" + |), + M.read (| new_idx |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_push : M.IsAssociatedFunction Self "push" push. + + (* + pub fn return_stack_len(&self) -> usize { + self.return_stack.len() + } + *) + Definition return_stack_len (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_interpreter::function_stack::FunctionReturnFrame"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionStack", + "return_stack" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_return_stack_len : + M.IsAssociatedFunction Self "return_stack_len" return_stack_len. + + (* + pub fn pop(&mut self) -> Option { + self.return_stack.pop().map(|frame| { + self.current_code_idx = frame.idx; + frame + }) + } + *) + Definition pop (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_interpreter::function_stack::FunctionReturnFrame" ], + "map", + [ + Ty.path "revm_interpreter::function_stack::FunctionReturnFrame"; + Ty.function + [ Ty.tuple [ Ty.path "revm_interpreter::function_stack::FunctionReturnFrame" ] ] + (Ty.path "revm_interpreter::function_stack::FunctionReturnFrame") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_interpreter::function_stack::FunctionReturnFrame"; + Ty.path "alloc::alloc::Global" + ], + "pop", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionStack", + "return_stack" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let frame := M.copy (| ฮณ |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionStack", + "current_code_idx" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + frame, + "revm_interpreter::function_stack::FunctionReturnFrame", + "idx" + |) + |) + |) in + frame + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop : M.IsAssociatedFunction Self "pop" pop. + + (* + pub fn set_current_code_idx(&mut self, idx: usize) { + self.current_code_idx = idx; + } + *) + Definition set_current_code_idx (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; idx ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let idx := M.alloc (| idx |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::function_stack::FunctionStack", + "current_code_idx" + |), + M.read (| idx |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_current_code_idx : + M.IsAssociatedFunction Self "set_current_code_idx" set_current_code_idx. + End Impl_revm_interpreter_function_stack_FunctionStack. +End function_stack. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas.md new file mode 100644 index 00000000..b993dee0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas.md @@ -0,0 +1,814 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/gas.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module gas. + (* StructRecord + { + name := "Gas"; + ty_params := []; + fields := + [ ("limit", Ty.path "u64"); ("remaining", Ty.path "u64"); ("refunded", Ty.path "i64") ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_gas_Gas. + + Module Impl_core_marker_Copy_for_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_gas_Gas. + + Module Impl_core_fmt_Debug_for_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Gas" |); + M.read (| Value.String "limit" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "limit" + |)); + M.read (| Value.String "remaining" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "remaining" + |)); + M.read (| Value.String "refunded" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "refunded" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_gas_Gas. + + Module Impl_core_default_Default_for_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::gas::Gas" + [ + ("limit", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u64", + [], + "default", + [] + |), + [] + |)); + ("remaining", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u64", + [], + "default", + [] + |), + [] + |)); + ("refunded", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "i64", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_gas_Gas. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_gas_Gas. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "limit" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::gas::Gas", + "limit" + |) + |)), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "remaining" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::gas::Gas", + "remaining" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "refunded" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::gas::Gas", + "refunded" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_gas_Gas. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_gas_Gas. + + Module Impl_core_cmp_Eq_for_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_gas_Gas. + + Module Impl_core_hash_Hash_for_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u64", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "limit" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u64", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "remaining" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "i64", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "refunded" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_gas_Gas. + + Module Impl_revm_interpreter_gas_Gas. + Definition Self : Ty.t := Ty.path "revm_interpreter::gas::Gas". + + (* + pub const fn new(limit: u64) -> Self { + Self { + limit, + remaining: limit, + refunded: 0, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ limit ] => + ltac:(M.monadic + (let limit := M.alloc (| limit |) in + Value.StructRecord + "revm_interpreter::gas::Gas" + [ + ("limit", M.read (| limit |)); + ("remaining", M.read (| limit |)); + ("refunded", Value.Integer 0) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub const fn new_spent(limit: u64) -> Self { + Self { + limit, + remaining: 0, + refunded: 0, + } + } + *) + Definition new_spent (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ limit ] => + ltac:(M.monadic + (let limit := M.alloc (| limit |) in + Value.StructRecord + "revm_interpreter::gas::Gas" + [ + ("limit", M.read (| limit |)); + ("remaining", Value.Integer 0); + ("refunded", Value.Integer 0) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_spent : M.IsAssociatedFunction Self "new_spent" new_spent. + + (* + pub const fn limit(&self) -> u64 { + self.limit + } + *) + Definition limit (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "limit" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_limit : M.IsAssociatedFunction Self "limit" limit. + + (* + pub const fn memory(&self) -> u64 { + 0 + } + *) + Definition memory (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Integer 0)) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_memory : M.IsAssociatedFunction Self "memory" memory. + + (* + pub const fn refunded(&self) -> i64 { + self.refunded + } + *) + Definition refunded (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "refunded" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_refunded : M.IsAssociatedFunction Self "refunded" refunded. + + (* + pub const fn spent(&self) -> u64 { + self.limit - self.remaining + } + *) + Definition spent (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.sub + Integer.U64 + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "limit" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "remaining" + |) + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_spent : M.IsAssociatedFunction Self "spent" spent. + + (* + pub const fn spend(&self) -> u64 { + self.spent() + } + *) + Definition spend (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| Ty.path "revm_interpreter::gas::Gas", "spent", [] |), + [ M.read (| self |) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_spend : M.IsAssociatedFunction Self "spend" spend. + + (* + pub const fn remaining(&self) -> u64 { + self.remaining + } + *) + Definition remaining (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "remaining" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_remaining : M.IsAssociatedFunction Self "remaining" remaining. + + (* + pub fn erase_cost(&mut self, returned: u64) { + self.remaining += returned; + } + *) + Definition erase_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; returned ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let returned := M.alloc (| returned |) in + M.read (| + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "remaining" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.add Integer.U64 (M.read (| ฮฒ |)) (M.read (| returned |)) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_erase_cost : M.IsAssociatedFunction Self "erase_cost" erase_cost. + + (* + pub fn spend_all(&mut self) { + self.remaining = 0; + } + *) + Definition spend_all (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "remaining" + |), + Value.Integer 0 + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_spend_all : M.IsAssociatedFunction Self "spend_all" spend_all. + + (* + pub fn record_refund(&mut self, refund: i64) { + self.refunded += refund; + } + *) + Definition record_refund (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; refund ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let refund := M.alloc (| refund |) in + M.read (| + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "refunded" + |) in + M.write (| ฮฒ, BinOp.Wrap.add Integer.I64 (M.read (| ฮฒ |)) (M.read (| refund |)) |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_record_refund : + M.IsAssociatedFunction Self "record_refund" record_refund. + + (* + pub fn set_final_refund(&mut self, is_london: bool) { + let max_refund_quotient = if is_london { 5 } else { 2 }; + self.refunded = (self.refunded() as u64).min(self.spent() / max_refund_quotient) as i64; + } + *) + Definition set_final_refund (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; is_london ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let is_london := M.alloc (| is_london |) in + M.read (| + let~ max_refund_quotient := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use is_london in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| Value.Integer 5 |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 2 |))) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "refunded" + |), + M.rust_cast + (M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "u64", [], "min", [] |), + [ + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ M.read (| self |) ] + |)); + BinOp.Wrap.div + Integer.U64 + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "spent", + [] + |), + [ M.read (| self |) ] + |)) + (M.read (| max_refund_quotient |)) + ] + |)) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_final_refund : + M.IsAssociatedFunction Self "set_final_refund" set_final_refund. + + (* + pub fn set_refund(&mut self, refund: i64) { + self.refunded = refund; + } + *) + Definition set_refund (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; refund ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let refund := M.alloc (| refund |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "refunded" + |), + M.read (| refund |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_refund : M.IsAssociatedFunction Self "set_refund" set_refund. + + (* + pub fn record_cost(&mut self, cost: u64) -> bool { + let (remaining, overflow) = self.remaining.overflowing_sub(cost); + let success = !overflow; + if success { + self.remaining = remaining; + } + success + } + *) + Definition record_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; cost ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let cost := M.alloc (| cost |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "overflowing_sub", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "remaining" + |) + |); + M.read (| cost |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let remaining := M.copy (| ฮณ0_0 |) in + let overflow := M.copy (| ฮณ0_1 |) in + let~ success := M.alloc (| UnOp.Pure.not (M.read (| overflow |)) |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use success in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::gas::Gas", + "remaining" + |), + M.read (| remaining |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + success)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_record_cost : M.IsAssociatedFunction Self "record_cost" record_cost. + End Impl_revm_interpreter_gas_Gas. +End gas. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas/calc.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas/calc.md new file mode 100644 index 00000000..1fe33249 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas/calc.md @@ -0,0 +1,3455 @@ +# ๐Ÿ“ calc.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/gas/calc.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module gas. + Module calc. + (* + pub fn sstore_refund(spec_id: SpecId, original: U256, current: U256, new: U256) -> i64 { + if spec_id.is_enabled_in(SpecId::ISTANBUL) { + // EIP-3529: Reduction in refunds + let sstore_clears_schedule = if spec_id.is_enabled_in(SpecId::LONDON) { + (SSTORE_RESET - COLD_SLOAD_COST + ACCESS_LIST_STORAGE_KEY) as i64 + } else { + REFUND_SSTORE_CLEARS + }; + if current == new { + 0 + } else { + if original == current && new == U256::ZERO { + sstore_clears_schedule + } else { + let mut refund = 0; + + if original != U256::ZERO { + if current == U256::ZERO { + refund -= sstore_clears_schedule; + } else if new == U256::ZERO { + refund += sstore_clears_schedule; + } + } + + if original == new { + let (gas_sstore_reset, gas_sload) = if spec_id.is_enabled_in(SpecId::BERLIN) { + (SSTORE_RESET - COLD_SLOAD_COST, WARM_STORAGE_READ_COST) + } else { + (SSTORE_RESET, sload_cost(spec_id, false)) + }; + if original == U256::ZERO { + refund += (SSTORE_SET - gas_sload) as i64; + } else { + refund += (gas_sstore_reset - gas_sload) as i64; + } + } + + refund + } + } + } else { + if current != U256::ZERO && new == U256::ZERO { + REFUND_SSTORE_CLEARS + } else { + 0 + } + } + } + *) + Definition sstore_refund (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id; original; current; new ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + let original := M.alloc (| original |) in + let current := M.alloc (| current |) in + let new := M.alloc (| new |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::ISTANBUL" + [] + ] + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ sstore_clears_schedule := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::LONDON" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.rust_cast + (BinOp.Wrap.add + Integer.U64 + (BinOp.Wrap.sub + Integer.U64 + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::SSTORE_RESET" + |) + |)) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::COLD_SLOAD_COST" + |) + |))) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::ACCESS_LIST_STORAGE_KEY" + |) + |))) + |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| + "revm_interpreter::gas::constants::REFUND_SSTORE_CLEARS" + |))) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ current; new ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| Value.Integer 0 |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ original; current ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ new; M.get_constant (| "ruint::ZERO" |) ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + sstore_clears_schedule)); + fun ฮณ => + ltac:(M.monadic + (let~ refund := M.alloc (| Value.Integer 0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ original; M.get_constant (| "ruint::ZERO" |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + current; + M.get_constant (| "ruint::ZERO" |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := refund in + M.write (| + ฮฒ, + BinOp.Wrap.sub + Integer.I64 + (M.read (| ฮฒ |)) + (M.read (| sstore_clears_schedule |)) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + new; + M.get_constant (| + "ruint::ZERO" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := refund in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.I64 + (M.read (| ฮฒ |)) + (M.read (| + sstore_clears_schedule + |)) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ original; new ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.Tuple + [ + BinOp.Wrap.sub + Integer.U64 + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::SSTORE_RESET" + |) + |)) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::COLD_SLOAD_COST" + |) + |)); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::WARM_STORAGE_READ_COST" + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple + [ + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::SSTORE_RESET" + |) + |); + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::sload_cost", + [] + |), + [ + M.read (| spec_id |); + Value.Bool false + ] + |) + ] + |))) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let gas_sstore_reset := M.copy (| ฮณ0_0 |) in + let gas_sload := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + original; + M.get_constant (| + "ruint::ZERO" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := refund in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.I64 + (M.read (| ฮฒ |)) + (M.rust_cast + (BinOp.Wrap.sub + Integer.U64 + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::SSTORE_SET" + |) + |)) + (M.read (| gas_sload |)))) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + let ฮฒ := refund in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.I64 + (M.read (| ฮฒ |)) + (M.rust_cast + (BinOp.Wrap.sub + Integer.U64 + (M.read (| + gas_sstore_reset + |)) + (M.read (| gas_sload |)))) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + refund)) + ] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ current; M.get_constant (| "ruint::ZERO" |) ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ new; M.get_constant (| "ruint::ZERO" |) ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.get_constant (| + "revm_interpreter::gas::constants::REFUND_SSTORE_CLEARS" + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 0 |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sstore_refund : + M.IsFunction "revm_interpreter::gas::calc::sstore_refund" sstore_refund. + + (* + pub const fn create2_cost(len: u64) -> Option { + CREATE.checked_add(tri!(cost_per_word(len, KECCAK256WORD))) + } + *) + Definition create2_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ len ] => + ltac:(M.monadic + (let len := M.alloc (| len |) in + M.catch_return (| + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| Ty.path "u64", "checked_add", [] |), + [ + M.read (| M.get_constant (| "revm_interpreter::gas::constants::CREATE" |) |); + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::cost_per_word", [] |), + [ + M.read (| len |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::KECCAK256WORD" |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let v := M.copy (| ฮณ0_0 |) in + v)); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| Value.StructTuple "core::option::Option::None" [] |) + |) + |) + |))) + ] + |) + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_create2_cost : + M.IsFunction "revm_interpreter::gas::calc::create2_cost" create2_cost. + + (* + const fn log2floor(value: U256) -> u64 { + let mut l: u64 = 256; + let mut i = 3; + loop { + if value.as_limbs()[i] == 0u64 { + l -= 64; + } else { + l -= value.as_limbs()[i].leading_zeros() as u64; + if l == 0 { + return l; + } else { + return l - 1; + } + } + if i == 0 { + break; + } + i -= 1; + } + l + } + *) + Definition log2floor (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ l := M.alloc (| Value.Integer 256 |) in + let~ i := M.alloc (| Value.Integer 3 |) in + let~ _ := + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ value ] + |), + i + |) + |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := l in + M.write (| + ฮฒ, + BinOp.Wrap.sub Integer.U64 (M.read (| ฮฒ |)) (Value.Integer 64) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + let ฮฒ := l in + M.write (| + ฮฒ, + BinOp.Wrap.sub + Integer.U64 + (M.read (| ฮฒ |)) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "leading_zeros", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ value ] + |), + i + |) + |) + ] + |))) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| l |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.return_ (| M.read (| l |) |) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + BinOp.Wrap.sub + Integer.U64 + (M.read (| l |)) + (Value.Integer 1) + |) + |) + |) + |))) + ] + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| i |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| M.never_to_any (| M.read (| M.break (||) |) |) |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + let ฮฒ := i in + M.write (| + ฮฒ, + BinOp.Wrap.sub Integer.Usize (M.read (| ฮฒ |)) (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))) + |) in + l + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_log2floor : M.IsFunction "revm_interpreter::gas::calc::log2floor" log2floor. + + (* + pub fn exp_cost(spec_id: SpecId, power: U256) -> Option { + if power == U256::ZERO { + Some(EXP) + } else { + // EIP-160: EXP cost increase + let gas_byte = U256::from(if spec_id.is_enabled_in(SpecId::SPURIOUS_DRAGON) { + 50 + } else { + 10 + }); + let gas = U256::from(EXP) + .checked_add(gas_byte.checked_mul(U256::from(log2floor(power) / 8 + 1))?)?; + + u64::try_from(gas).ok() + } + } + *) + Definition exp_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id; power ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + let power := M.alloc (| power |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ power; M.get_constant (| "ruint::ZERO" |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::EXP" |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ gas_byte := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| Value.Integer 50 |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 10 |))) + ] + |) + |) + ] + |) + |) in + let~ gas := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "checked_add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::EXP" + |) + |) + ] + |); + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "checked_mul", + [] + |), + [ + M.read (| gas_byte |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + BinOp.Wrap.add + Integer.U64 + (BinOp.Wrap.div + Integer.U64 + (M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::log2floor", + [] + |), + [ M.read (| power |) ] + |)) + (Value.Integer 8)) + (Value.Integer 1) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "u64" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "core::convert::Infallible" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "u64" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "core::convert::Infallible" ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply (Ty.path "ruint::from::FromUintError") [ Ty.path "u64" ] + ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "u64", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ M.read (| gas |) ] + |) + ] + |) + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_exp_cost : M.IsFunction "revm_interpreter::gas::calc::exp_cost" exp_cost. + + (* + pub const fn verylowcopy_cost(len: u64) -> Option { + VERYLOW.checked_add(tri!(cost_per_word(len, COPY))) + } + *) + Definition verylowcopy_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ len ] => + ltac:(M.monadic + (let len := M.alloc (| len |) in + M.catch_return (| + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| Ty.path "u64", "checked_add", [] |), + [ + M.read (| M.get_constant (| "revm_interpreter::gas::constants::VERYLOW" |) |); + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::cost_per_word", [] |), + [ + M.read (| len |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::COPY" |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let v := M.copy (| ฮณ0_0 |) in + v)); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| Value.StructTuple "core::option::Option::None" [] |) + |) + |) + |))) + ] + |) + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_verylowcopy_cost : + M.IsFunction "revm_interpreter::gas::calc::verylowcopy_cost" verylowcopy_cost. + + (* + pub const fn extcodecopy_cost(spec_id: SpecId, len: u64, is_cold: bool) -> Option { + let base_gas = if spec_id.is_enabled_in(SpecId::BERLIN) { + warm_cold_cost(is_cold) + } else if spec_id.is_enabled_in(SpecId::TANGERINE) { + 700 + } else { + 20 + }; + base_gas.checked_add(tri!(cost_per_word(len, COPY))) + } + *) + Definition extcodecopy_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id; len; is_cold ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + let len := M.alloc (| len |) in + let is_cold := M.alloc (| is_cold |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ base_gas := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::warm_cold_cost", + [] + |), + [ M.read (| is_cold |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::TANGERINE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| Value.Integer 700 |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 20 |))) + ] + |))) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "checked_add", [] |), + [ + M.read (| base_gas |); + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::cost_per_word", [] |), + [ + M.read (| len |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::COPY" |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let v := M.copy (| ฮณ0_0 |) in + v)); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))) + ] + |) + |) + ] + |) + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_extcodecopy_cost : + M.IsFunction "revm_interpreter::gas::calc::extcodecopy_cost" extcodecopy_cost. + + (* + pub const fn log_cost(n: u8, len: u64) -> Option { + tri!(LOG.checked_add(tri!(LOGDATA.checked_mul(len)))).checked_add(LOGTOPIC * n as u64) + } + *) + Definition log_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ n; len ] => + ltac:(M.monadic + (let n := M.alloc (| n |) in + let len := M.alloc (| len |) in + M.catch_return (| + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| Ty.path "u64", "checked_add", [] |), + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "checked_add", [] |), + [ + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOG" |) + |); + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "checked_mul", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::LOGDATA" + |) + |); + M.read (| len |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let v := M.copy (| ฮณ0_0 |) in + v)); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))) + ] + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let v := M.copy (| ฮณ0_0 |) in + v)); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| Value.StructTuple "core::option::Option::None" [] |) + |) + |) + |))) + ] + |) + |); + BinOp.Wrap.mul + Integer.U64 + (M.read (| M.get_constant (| "revm_interpreter::gas::constants::LOGTOPIC" |) |)) + (M.rust_cast (M.read (| n |))) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_log_cost : M.IsFunction "revm_interpreter::gas::calc::log_cost" log_cost. + + (* + pub const fn keccak256_cost(len: u64) -> Option { + KECCAK256.checked_add(tri!(cost_per_word(len, KECCAK256WORD))) + } + *) + Definition keccak256_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ len ] => + ltac:(M.monadic + (let len := M.alloc (| len |) in + M.catch_return (| + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| Ty.path "u64", "checked_add", [] |), + [ + M.read (| M.get_constant (| "revm_interpreter::gas::constants::KECCAK256" |) |); + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::cost_per_word", [] |), + [ + M.read (| len |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::KECCAK256WORD" |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let v := M.copy (| ฮณ0_0 |) in + v)); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| Value.StructTuple "core::option::Option::None" [] |) + |) + |) + |))) + ] + |) + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_keccak256_cost : + M.IsFunction "revm_interpreter::gas::calc::keccak256_cost" keccak256_cost. + + (* + pub const fn cost_per_word(len: u64, multiple: u64) -> Option { + multiple.checked_mul(num_words(len)) + } + *) + Definition cost_per_word (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ len; multiple ] => + ltac:(M.monadic + (let len := M.alloc (| len |) in + let multiple := M.alloc (| multiple |) in + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "checked_mul", [] |), + [ + M.read (| multiple |); + M.call_closure (| + M.get_function (| "revm_interpreter::interpreter::shared_memory::num_words", [] |), + [ M.read (| len |) ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_cost_per_word : + M.IsFunction "revm_interpreter::gas::calc::cost_per_word" cost_per_word. + + (* + pub const fn initcode_cost(len: u64) -> u64 { + let Some(cost) = cost_per_word(len, INITCODE_WORD_COST) else { + panic!("initcode cost overflow") + }; + cost + } + *) + Definition initcode_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ len ] => + ltac:(M.monadic + (let len := M.alloc (| len |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::cost_per_word", [] |), + [ + M.read (| len |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::INITCODE_WORD_COST" |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let cost := M.copy (| ฮณ0_0 |) in + cost)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_initcode_cost : + M.IsFunction "revm_interpreter::gas::calc::initcode_cost" initcode_cost. + + (* + pub const fn sload_cost(spec_id: SpecId, is_cold: bool) -> u64 { + if spec_id.is_enabled_in(SpecId::BERLIN) { + if is_cold { + COLD_SLOAD_COST + } else { + WARM_STORAGE_READ_COST + } + } else if spec_id.is_enabled_in(SpecId::ISTANBUL) { + // EIP-1884: Repricing for trie-size-dependent opcodes + INSTANBUL_SLOAD_GAS + } else if spec_id.is_enabled_in(SpecId::TANGERINE) { + // EIP-150: Gas cost changes for IO-heavy operations + 200 + } else { + 50 + } + } + *) + Definition sload_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id; is_cold ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + let is_cold := M.alloc (| is_cold |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple "revm_primitives::specification::SpecId::BERLIN" [] + ] + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use is_cold in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.get_constant (| + "revm_interpreter::gas::constants::COLD_SLOAD_COST" + |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| + "revm_interpreter::gas::constants::WARM_STORAGE_READ_COST" + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::ISTANBUL" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.get_constant (| + "revm_interpreter::gas::constants::INSTANBUL_SLOAD_GAS" + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::TANGERINE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| Value.Integer 200 |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 50 |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sload_cost : M.IsFunction "revm_interpreter::gas::calc::sload_cost" sload_cost. + + (* + pub fn sstore_cost( + spec_id: SpecId, + original: U256, + current: U256, + new: U256, + gas: u64, + is_cold: bool, + ) -> Option { + // EIP-1706 Disable SSTORE with gasleft lower than call stipend + if spec_id.is_enabled_in(SpecId::ISTANBUL) && gas <= CALL_STIPEND { + return None; + } + + if spec_id.is_enabled_in(SpecId::BERLIN) { + // Berlin specification logic + let mut gas_cost = istanbul_sstore_cost::( + original, current, new, + ); + + if is_cold { + gas_cost += COLD_SLOAD_COST; + } + Some(gas_cost) + } else if spec_id.is_enabled_in(SpecId::ISTANBUL) { + // Istanbul logic + Some(istanbul_sstore_cost::( + original, current, new, + )) + } else { + // Frontier logic + Some(frontier_sstore_cost(current, new)) + } + } + *) + Definition sstore_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id; original; current; new; gas; is_cold ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + let original := M.alloc (| original |) in + let current := M.alloc (| current |) in + let new := M.alloc (| new |) in + let gas := M.alloc (| gas |) in + let is_cold := M.alloc (| is_cold |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::ISTANBUL" + [] + ] + |), + ltac:(M.monadic + (BinOp.Pure.le + (M.read (| gas |)) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::CALL_STIPEND" + |) + |)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| Value.StructTuple "core::option::Option::None" [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ gas_cost := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::istanbul_sstore_cost", + [] + |), + [ M.read (| original |); M.read (| current |); M.read (| new |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use is_cold in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := gas_cost in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::COLD_SLOAD_COST" + |) + |)) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| gas_cost |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::ISTANBUL" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::istanbul_sstore_cost", + [] + |), + [ + M.read (| original |); + M.read (| current |); + M.read (| new |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::frontier_sstore_cost", + [] + |), + [ M.read (| current |); M.read (| new |) ] + |) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sstore_cost : + M.IsFunction "revm_interpreter::gas::calc::sstore_cost" sstore_cost. + + (* + fn istanbul_sstore_cost( + original: U256, + current: U256, + new: U256, + ) -> u64 { + if new == current { + SLOAD_GAS + } else if original == current && original == U256::ZERO { + SSTORE_SET + } else if original == current { + SSTORE_RESET_GAS + } else { + SLOAD_GAS + } + } + *) + Definition istanbul_sstore_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ original; current; new ] => + ltac:(M.monadic + (let original := M.alloc (| original |) in + let current := M.alloc (| current |) in + let new := M.alloc (| new |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ new; current ] + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.get_constant (| + "revm_interpreter::gas::calc::istanbul_sstore_cost::SLOAD_GAS" + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ original; current ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ original; M.get_constant (| "ruint::ZERO" |) ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.get_constant (| "revm_interpreter::gas::constants::SSTORE_SET" |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ original; current ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.get_constant (| + "revm_interpreter::gas::calc::istanbul_sstore_cost::SSTORE_RESET_GAS" + |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| + "revm_interpreter::gas::calc::istanbul_sstore_cost::SLOAD_GAS" + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_istanbul_sstore_cost : + M.IsFunction "revm_interpreter::gas::calc::istanbul_sstore_cost" istanbul_sstore_cost. + + (* + fn frontier_sstore_cost(current: U256, new: U256) -> u64 { + if current == U256::ZERO && new != U256::ZERO { + SSTORE_SET + } else { + SSTORE_RESET + } + } + *) + Definition frontier_sstore_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ current; new ] => + ltac:(M.monadic + (let current := M.alloc (| current |) in + let new := M.alloc (| new |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ current; M.get_constant (| "ruint::ZERO" |) ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ new; M.get_constant (| "ruint::ZERO" |) ] + |))) + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.get_constant (| "revm_interpreter::gas::constants::SSTORE_SET" |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| "revm_interpreter::gas::constants::SSTORE_RESET" |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_frontier_sstore_cost : + M.IsFunction "revm_interpreter::gas::calc::frontier_sstore_cost" frontier_sstore_cost. + + (* + pub const fn selfdestruct_cost(spec_id: SpecId, res: SelfDestructResult) -> u64 { + // EIP-161: State trie clearing (invariant-preserving alternative) + let should_charge_topup = if spec_id.is_enabled_in(SpecId::SPURIOUS_DRAGON) { + res.had_value && !res.target_exists + } else { + !res.target_exists + }; + + // EIP-150: Gas cost changes for IO-heavy operations + let selfdestruct_gas_topup = if spec_id.is_enabled_in(SpecId::TANGERINE) && should_charge_topup + { + 25000 + } else { + 0 + }; + + // EIP-150: Gas cost changes for IO-heavy operations + let selfdestruct_gas = if spec_id.is_enabled_in(SpecId::TANGERINE) { + 5000 + } else { + 0 + }; + + let mut gas = selfdestruct_gas + selfdestruct_gas_topup; + if spec_id.is_enabled_in(SpecId::BERLIN) && res.is_cold { + gas += COLD_ACCOUNT_ACCESS_COST + } + gas + } + *) + Definition selfdestruct_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id; res ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + let res := M.alloc (| res |) in + M.read (| + let~ should_charge_topup := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + LogicalOp.and (| + M.read (| + M.SubPointer.get_struct_record_field (| + res, + "revm_interpreter::host::SelfDestructResult", + "had_value" + |) + |), + ltac:(M.monadic + (UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + res, + "revm_interpreter::host::SelfDestructResult", + "target_exists" + |) + |)))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + res, + "revm_interpreter::host::SelfDestructResult", + "target_exists" + |) + |)) + |))) + ] + |) + |) in + let~ selfdestruct_gas_topup := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::TANGERINE" + [] + ] + |), + ltac:(M.monadic (M.read (| should_charge_topup |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| Value.Integer 25000 |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 0 |))) + ] + |) + |) in + let~ selfdestruct_gas := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::TANGERINE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| Value.Integer 5000 |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 0 |))) + ] + |) + |) in + let~ gas := + M.alloc (| + BinOp.Wrap.add + Integer.U64 + (M.read (| selfdestruct_gas |)) + (M.read (| selfdestruct_gas_topup |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |), + ltac:(M.monadic + (M.read (| + M.SubPointer.get_struct_record_field (| + res, + "revm_interpreter::host::SelfDestructResult", + "is_cold" + |) + |))) + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let ฮฒ := gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::COLD_ACCOUNT_ACCESS_COST" + |) + |)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + gas + |))) + | _, _ => M.impossible + end. + + Axiom Function_selfdestruct_cost : + M.IsFunction "revm_interpreter::gas::calc::selfdestruct_cost" selfdestruct_cost. + + (* + pub const fn call_cost( + spec_id: SpecId, + transfers_value: bool, + is_cold: bool, + new_account_accounting: bool, + ) -> u64 { + // Account access. + let mut gas = if spec_id.is_enabled_in(SpecId::BERLIN) { + warm_cold_cost(is_cold) + } else if spec_id.is_enabled_in(SpecId::TANGERINE) { + // EIP-150: Gas cost changes for IO-heavy operations + 700 + } else { + 40 + }; + + // transfer value cost + if transfers_value { + gas += CALLVALUE; + } + + // new account cost + if new_account_accounting { + // EIP-161: State trie clearing (invariant-preserving alternative) + if spec_id.is_enabled_in(SpecId::SPURIOUS_DRAGON) { + // account only if there is value transferred. + if transfers_value { + gas += NEWACCOUNT; + } + } else { + gas += NEWACCOUNT; + } + } + + gas + } + *) + Definition call_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id; transfers_value; is_cold; new_account_accounting ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + let transfers_value := M.alloc (| transfers_value |) in + let is_cold := M.alloc (| is_cold |) in + let new_account_accounting := M.alloc (| new_account_accounting |) in + M.read (| + let~ gas := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::warm_cold_cost", [] |), + [ M.read (| is_cold |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::TANGERINE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| Value.Integer 700 |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 40 |))) + ] + |))) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use transfers_value in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + let ฮฒ := gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (M.read (| + M.get_constant (| "revm_interpreter::gas::constants::CALLVALUE" |) + |)) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use new_account_accounting in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use transfers_value in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::NEWACCOUNT" + |) + |)) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + let ฮฒ := gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::NEWACCOUNT" + |) + |)) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + gas + |))) + | _, _ => M.impossible + end. + + Axiom Function_call_cost : M.IsFunction "revm_interpreter::gas::calc::call_cost" call_cost. + + (* + pub const fn warm_cold_cost(is_cold: bool) -> u64 { + if is_cold { + COLD_ACCOUNT_ACCESS_COST + } else { + WARM_STORAGE_READ_COST + } + } + *) + Definition warm_cold_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ is_cold ] => + ltac:(M.monadic + (let is_cold := M.alloc (| is_cold |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use is_cold in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.get_constant (| + "revm_interpreter::gas::constants::COLD_ACCOUNT_ACCESS_COST" + |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| + "revm_interpreter::gas::constants::WARM_STORAGE_READ_COST" + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_warm_cold_cost : + M.IsFunction "revm_interpreter::gas::calc::warm_cold_cost" warm_cold_cost. + + (* + pub const fn memory_gas_for_len(len: usize) -> u64 { + memory_gas(crate::interpreter::num_words(len as u64)) + } + *) + Definition memory_gas_for_len (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ len ] => + ltac:(M.monadic + (let len := M.alloc (| len |) in + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::memory_gas", [] |), + [ + M.call_closure (| + M.get_function (| "revm_interpreter::interpreter::shared_memory::num_words", [] |), + [ M.rust_cast (M.read (| len |)) ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_memory_gas_for_len : + M.IsFunction "revm_interpreter::gas::calc::memory_gas_for_len" memory_gas_for_len. + + (* + pub const fn memory_gas(num_words: u64) -> u64 { + MEMORY + .saturating_mul(num_words) + .saturating_add(num_words.saturating_mul(num_words) / 512) + } + *) + Definition memory_gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ num_words ] => + ltac:(M.monadic + (let num_words := M.alloc (| num_words |) in + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "saturating_add", [] |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "saturating_mul", [] |), + [ + M.read (| M.get_constant (| "revm_interpreter::gas::constants::MEMORY" |) |); + M.read (| num_words |) + ] + |); + BinOp.Wrap.div + Integer.U64 + (M.call_closure (| + M.get_associated_function (| Ty.path "u64", "saturating_mul", [] |), + [ M.read (| num_words |); M.read (| num_words |) ] + |)) + (Value.Integer 512) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_memory_gas : M.IsFunction "revm_interpreter::gas::calc::memory_gas" memory_gas. + + (* + pub fn validate_initial_tx_gas( + spec_id: SpecId, + input: &[u8], + is_create: bool, + access_list: &[(Address, Vec)], + initcodes: &[Bytes], + ) -> u64 { + let mut initial_gas = 0; + let mut zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; + let mut non_zero_data_len = input.len() as u64 - zero_data_len; + + // Enabling of initcode is checked in `validate_env` handler. + for initcode in initcodes { + let zeros = initcode.iter().filter(|v| **v == 0).count() as u64; + zero_data_len += zeros; + non_zero_data_len += initcode.len() as u64 - zeros; + } + + // initdate stipend + initial_gas += zero_data_len * TRANSACTION_ZERO_DATA; + // EIP-2028: Transaction data gas cost reduction + initial_gas += non_zero_data_len + * if spec_id.is_enabled_in(SpecId::ISTANBUL) { + 16 + } else { + 68 + }; + + // get number of access list account and storages. + if spec_id.is_enabled_in(SpecId::BERLIN) { + let accessed_slots = access_list + .iter() + .fold(0, |slot_count, (_, slots)| slot_count + slots.len() as u64); + initial_gas += access_list.len() as u64 * ACCESS_LIST_ADDRESS; + initial_gas += accessed_slots * ACCESS_LIST_STORAGE_KEY; + } + + // base stipend + initial_gas += if is_create { + if spec_id.is_enabled_in(SpecId::HOMESTEAD) { + // EIP-2: Homestead Hard-fork Changes + 53000 + } else { + 21000 + } + } else { + 21000 + }; + + // EIP-3860: Limit and meter initcode + // Initcode stipend for bytecode analysis + if spec_id.is_enabled_in(SpecId::SHANGHAI) && is_create { + initial_gas += initcode_cost(input.len() as u64) + } + + initial_gas + } + *) + Definition validate_initial_tx_gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id; input; is_create; access_list; initcodes ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + let input := M.alloc (| input |) in + let is_create := M.alloc (| is_create |) in + let access_list := M.alloc (| access_list |) in + let initcodes := M.alloc (| initcodes |) in + M.read (| + let~ initial_gas := M.alloc (| Value.Integer 0 |) in + let~ zero_data_len := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::filter::Filter") + [ + Ty.apply (Ty.path "core::slice::iter::Iter") [ Ty.path "u8" ]; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "&") [ Ty.path "u8" ] ] + ] + ] + (Ty.path "bool") + ], + [], + "count", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply (Ty.path "core::slice::iter::Iter") [ Ty.path "u8" ], + [], + "filter", + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "&") [ Ty.path "u8" ] ] + ] + ] + (Ty.path "bool") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "iter", + [] + |), + [ M.read (| input |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let v := M.copy (| ฮณ |) in + BinOp.Pure.eq + (M.read (| M.read (| M.read (| v |) |) |)) + (Value.Integer 0))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |)) + |) in + let~ non_zero_data_len := + M.alloc (| + BinOp.Wrap.sub + Integer.U64 + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| input |) ] + |))) + (M.read (| zero_data_len |)) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ], + [], + "into_iter", + [] + |), + [ M.read (| initcodes |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let initcode := M.copy (| ฮณ0_0 |) in + let~ zeros := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::filter::Filter") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "u8" ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "u8" ] + ] + ] + ] + (Ty.path "bool") + ], + [], + "count", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "u8" ], + [], + "filter", + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "u8" ] + ] + ] + ] + (Ty.path "bool") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path + "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| initcode |) ] + |) + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let v := M.copy (| ฮณ |) in + BinOp.Pure.eq + (M.read (| + M.read (| M.read (| v |) |) + |)) + (Value.Integer 0))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |)) + |) in + let~ _ := + let ฮฒ := zero_data_len in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (M.read (| zeros |)) + |) in + let~ _ := + let ฮฒ := non_zero_data_len in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (BinOp.Wrap.sub + Integer.U64 + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| initcode |) ] + |) + ] + |))) + (M.read (| zeros |))) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + let ฮฒ := initial_gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (BinOp.Wrap.mul + Integer.U64 + (M.read (| zero_data_len |)) + (M.read (| + M.get_constant (| "revm_interpreter::gas::constants::TRANSACTION_ZERO_DATA" |) + |))) + |) in + let~ _ := + let ฮฒ := initial_gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (BinOp.Wrap.mul + Integer.U64 + (M.read (| non_zero_data_len |)) + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::ISTANBUL" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| Value.Integer 16 |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 68 |))) + ] + |) + |))) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ accessed_slots := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ] + ], + [], + "fold", + [ + Ty.path "u64"; + Ty.function + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.apply + (Ty.path "&") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ] + ] + ] + ] + ] + (Ty.path "u64") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" + ] + ] + ], + "iter", + [] + |), + [ M.read (| access_list |) ] + |); + Value.Integer 0; + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let slot_count := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let slots := M.alloc (| ฮณ1_1 |) in + BinOp.Wrap.add + Integer.U64 + (M.read (| slot_count |)) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ M.read (| slots |) ] + |))))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ _ := + let ฮฒ := initial_gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (BinOp.Wrap.mul + Integer.U64 + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "len", + [] + |), + [ M.read (| access_list |) ] + |))) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::ACCESS_LIST_ADDRESS" + |) + |))) + |) in + let~ _ := + let ฮฒ := initial_gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (BinOp.Wrap.mul + Integer.U64 + (M.read (| accessed_slots |)) + (M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::ACCESS_LIST_STORAGE_KEY" + |) + |))) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + let ฮฒ := initial_gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use is_create in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::HOMESTEAD" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| Value.Integer 53000 |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 21000 |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 21000 |))) + ] + |) + |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::SHANGHAI" + [] + ] + |), + ltac:(M.monadic (M.read (| is_create |))) + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let ฮฒ := initial_gas in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U64 + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::initcode_cost", [] |), + [ + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| input |) ] + |)) + ] + |)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + initial_gas + |))) + | _, _ => M.impossible + end. + + Axiom Function_validate_initial_tx_gas : + M.IsFunction "revm_interpreter::gas::calc::validate_initial_tx_gas" validate_initial_tx_gas. + End calc. +End gas. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas/constants.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas/constants.md new file mode 100644 index 00000000..42a2f137 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/gas/constants.md @@ -0,0 +1,127 @@ +# ๐Ÿ“ constants.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/gas/constants.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module gas. + Module constants. + Definition value_ZERO : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 0 |))). + + Definition value_BASE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 2 |))). + + Definition value_VERYLOW : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 3 |))). + + Definition value_DATA_LOADN_GAS : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 3 |))). + + Definition value_CONDITION_JUMP_GAS : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 4 |))). + + Definition value_RETF_GAS : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 4 |))). + + Definition value_DATA_LOAD_GAS : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 4 |))). + + Definition value_LOW : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 5 |))). + + Definition value_MID : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 8 |))). + + Definition value_HIGH : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 10 |))). + + Definition value_JUMPDEST : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 1 |))). + + Definition value_SELFDESTRUCT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 24000 |))). + + Definition value_CREATE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 32000 |))). + + Definition value_CALLVALUE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 9000 |))). + + Definition value_NEWACCOUNT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 25000 |))). + + Definition value_EXP : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 10 |))). + + Definition value_MEMORY : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 3 |))). + + Definition value_LOG : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 375 |))). + + Definition value_LOGDATA : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 8 |))). + + Definition value_LOGTOPIC : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 375 |))). + + Definition value_KECCAK256 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 30 |))). + + Definition value_KECCAK256WORD : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 6 |))). + + Definition value_COPY : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 3 |))). + + Definition value_BLOCKHASH : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 20 |))). + + Definition value_CODEDEPOSIT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 200 |))). + + Definition value_INSTANBUL_SLOAD_GAS : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 800 |))). + + Definition value_SSTORE_SET : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 20000 |))). + + Definition value_SSTORE_RESET : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 5000 |))). + + Definition value_REFUND_SSTORE_CLEARS : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 15000 |))). + + Definition value_TRANSACTION_ZERO_DATA : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 4 |))). + + Definition value_TRANSACTION_NON_ZERO_DATA_INIT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 16 |))). + + Definition value_TRANSACTION_NON_ZERO_DATA_FRONTIER : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 68 |))). + + Definition value_EOF_CREATE_GAS : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 32000 |))). + + Definition value_ACCESS_LIST_ADDRESS : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 2400 |))). + + Definition value_ACCESS_LIST_STORAGE_KEY : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 1900 |))). + + Definition value_COLD_SLOAD_COST : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 2100 |))). + + Definition value_COLD_ACCOUNT_ACCESS_COST : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 2600 |))). + + Definition value_WARM_STORAGE_READ_COST : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 100 |))). + + Definition value_WARM_SSTORE_RESET : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + BinOp.Wrap.sub + Integer.U64 + (M.read (| M.get_constant (| "revm_interpreter::gas::constants::SSTORE_RESET" |) |)) + (M.read (| + M.get_constant (| "revm_interpreter::gas::constants::COLD_SLOAD_COST" |) + |)) + |))). + + Definition value_INITCODE_WORD_COST : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 2 |))). + + Definition value_CALL_STIPEND : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 2300 |))). + End constants. +End gas. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/host.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/host.md new file mode 100644 index 00000000..3761ab63 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/host.md @@ -0,0 +1,1024 @@ +# ๐Ÿ“ host.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/host.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module host. + (* Trait *) + (* Empty module 'Host' *) + + (* StructRecord + { + name := "SStoreResult"; + ty_params := []; + fields := + [ + ("original_value", Ty.path "ruint::Uint"); + ("present_value", Ty.path "ruint::Uint"); + ("new_value", Ty.path "ruint::Uint"); + ("is_cold", Ty.path "bool") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_host_SStoreResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SStoreResult". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "SStoreResult" |); + M.read (| Value.String "original_value" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "original_value" + |)); + M.read (| Value.String "present_value" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "present_value" + |)); + M.read (| Value.String "new_value" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "new_value" + |)); + M.read (| Value.String "is_cold" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "is_cold" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_host_SStoreResult. + + Module Impl_core_clone_Clone_for_revm_interpreter_host_SStoreResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SStoreResult". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::host::SStoreResult" + [ + ("original_value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "original_value" + |) + ] + |)); + ("present_value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "present_value" + |) + ] + |)); + ("new_value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "new_value" + |) + ] + |)); + ("is_cold", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "bool", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "is_cold" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_host_SStoreResult. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_host_SStoreResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SStoreResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_host_SStoreResult. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_host_SStoreResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SStoreResult". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "original_value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::SStoreResult", + "original_value" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "present_value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::SStoreResult", + "present_value" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "new_value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::SStoreResult", + "new_value" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SStoreResult", + "is_cold" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::SStoreResult", + "is_cold" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_host_SStoreResult. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_host_SStoreResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SStoreResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_host_SStoreResult. + + Module Impl_core_cmp_Eq_for_revm_interpreter_host_SStoreResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SStoreResult". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_host_SStoreResult. + + (* StructRecord + { + name := "LoadAccountResult"; + ty_params := []; + fields := [ ("is_cold", Ty.path "bool"); ("is_empty", Ty.path "bool") ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_host_LoadAccountResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::LoadAccountResult". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "LoadAccountResult" |); + M.read (| Value.String "is_cold" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |)); + M.read (| Value.String "is_empty" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::LoadAccountResult", + "is_empty" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_host_LoadAccountResult. + + Module Impl_core_clone_Clone_for_revm_interpreter_host_LoadAccountResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::LoadAccountResult". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::host::LoadAccountResult" + [ + ("is_cold", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "bool", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |) + ] + |)); + ("is_empty", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "bool", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::LoadAccountResult", + "is_empty" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_host_LoadAccountResult. + + Module Impl_core_default_Default_for_revm_interpreter_host_LoadAccountResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::LoadAccountResult". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::host::LoadAccountResult" + [ + ("is_cold", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)); + ("is_empty", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_host_LoadAccountResult. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_host_LoadAccountResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::LoadAccountResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_host_LoadAccountResult. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_host_LoadAccountResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::LoadAccountResult". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |) + |)), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::LoadAccountResult", + "is_empty" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::LoadAccountResult", + "is_empty" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_host_LoadAccountResult. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_host_LoadAccountResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::LoadAccountResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_host_LoadAccountResult. + + Module Impl_core_cmp_Eq_for_revm_interpreter_host_LoadAccountResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::LoadAccountResult". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_host_LoadAccountResult. + + (* StructRecord + { + name := "SelfDestructResult"; + ty_params := []; + fields := + [ + ("had_value", Ty.path "bool"); + ("target_exists", Ty.path "bool"); + ("is_cold", Ty.path "bool"); + ("previously_destroyed", Ty.path "bool") + ]; + } *) + + Module Impl_core_default_Default_for_revm_interpreter_host_SelfDestructResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SelfDestructResult". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::host::SelfDestructResult" + [ + ("had_value", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)); + ("target_exists", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)); + ("is_cold", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)); + ("previously_destroyed", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_host_SelfDestructResult. + + Module Impl_core_clone_Clone_for_revm_interpreter_host_SelfDestructResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SelfDestructResult". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::host::SelfDestructResult" + [ + ("had_value", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "bool", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "had_value" + |) + ] + |)); + ("target_exists", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "bool", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "target_exists" + |) + ] + |)); + ("is_cold", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "bool", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "is_cold" + |) + ] + |)); + ("previously_destroyed", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "bool", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "previously_destroyed" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_host_SelfDestructResult. + + Module Impl_core_fmt_Debug_for_revm_interpreter_host_SelfDestructResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SelfDestructResult". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "SelfDestructResult" |); + M.read (| Value.String "had_value" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "had_value" + |)); + M.read (| Value.String "target_exists" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "target_exists" + |)); + M.read (| Value.String "is_cold" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "is_cold" + |)); + M.read (| Value.String "previously_destroyed" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "previously_destroyed" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_host_SelfDestructResult. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_host_SelfDestructResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SelfDestructResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_host_SelfDestructResult. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_host_SelfDestructResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SelfDestructResult". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "had_value" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::SelfDestructResult", + "had_value" + |) + |)), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "target_exists" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::SelfDestructResult", + "target_exists" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "is_cold" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::SelfDestructResult", + "is_cold" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "previously_destroyed" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::SelfDestructResult", + "previously_destroyed" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_host_SelfDestructResult. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_host_SelfDestructResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SelfDestructResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_host_SelfDestructResult. + + Module Impl_core_cmp_Eq_for_revm_interpreter_host_SelfDestructResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SelfDestructResult". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_host_SelfDestructResult. + + Module Impl_core_hash_Hash_for_revm_interpreter_host_SelfDestructResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::SelfDestructResult". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "bool", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "had_value" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "bool", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "target_exists" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "bool", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "is_cold" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "bool", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::SelfDestructResult", + "previously_destroyed" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_host_SelfDestructResult. +End host. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/host/dummy.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/host/dummy.md new file mode 100644 index 00000000..68432b19 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/host/dummy.md @@ -0,0 +1,1238 @@ +# ๐Ÿ“ dummy.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/host/dummy.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module host. + Module dummy. + (* StructRecord + { + name := "DummyHost"; + ty_params := []; + fields := + [ + ("env", Ty.path "revm_primitives::env::Env"); + ("storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ]); + ("transient_storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ]); + ("log", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_host_dummy_DummyHost. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::dummy::DummyHost". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::host::dummy::DummyHost" + [ + ("env", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::Env", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "env" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "storage" + |) + ] + |)); + ("transient_storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "transient_storage" + |) + ] + |)); + ("log", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "log" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_host_dummy_DummyHost. + + Module Impl_core_fmt_Debug_for_revm_interpreter_host_dummy_DummyHost. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::dummy::DummyHost". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "DummyHost" |); + M.read (| Value.String "env" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "env" + |)); + M.read (| Value.String "storage" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "storage" + |)); + M.read (| Value.String "transient_storage" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "transient_storage" + |)); + M.read (| Value.String "log" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "log" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_host_dummy_DummyHost. + + Module Impl_core_default_Default_for_revm_interpreter_host_dummy_DummyHost. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::dummy::DummyHost". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::host::dummy::DummyHost" + [ + ("env", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::env::Env", + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("transient_storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("log", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_host_dummy_DummyHost. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_host_dummy_DummyHost. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::dummy::DummyHost". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_host_dummy_DummyHost. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_host_dummy_DummyHost. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::dummy::DummyHost". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::Env", + [ Ty.path "revm_primitives::env::Env" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "env" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::dummy::DummyHost", + "env" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "storage" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::dummy::DummyHost", + "storage" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "transient_storage" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::dummy::DummyHost", + "transient_storage" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "log" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::host::dummy::DummyHost", + "log" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_host_dummy_DummyHost. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_host_dummy_DummyHost. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::dummy::DummyHost". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_host_dummy_DummyHost. + + Module Impl_core_cmp_Eq_for_revm_interpreter_host_dummy_DummyHost. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::dummy::DummyHost". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_host_dummy_DummyHost. + + Module Impl_revm_interpreter_host_dummy_DummyHost. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::dummy::DummyHost". + + (* + pub fn new(env: Env) -> Self { + Self { + env, + ..Default::default() + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ env ] => + ltac:(M.monadic + (let env := M.alloc (| env |) in + M.struct_record_update + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_interpreter::host::dummy::DummyHost", + [], + "default", + [] + |), + [] + |)) + [ ("env", M.read (| env |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn clear(&mut self) { + self.storage.clear(); + self.log.clear(); + } + *) + Definition clear (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "clear", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "storage" + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + "clear", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "log" + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_clear : M.IsAssociatedFunction Self "clear" clear. + End Impl_revm_interpreter_host_dummy_DummyHost. + + Module Impl_revm_interpreter_host_Host_for_revm_interpreter_host_dummy_DummyHost. + Definition Self : Ty.t := Ty.path "revm_interpreter::host::dummy::DummyHost". + + (* + fn env(&self) -> &Env { + &self.env + } + *) + Definition env (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "env" + |))) + | _, _ => M.impossible + end. + + (* + fn env_mut(&mut self) -> &mut Env { + &mut self.env + } + *) + Definition env_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "env" + |))) + | _, _ => M.impossible + end. + + (* + fn load_account(&mut self, _address: Address) -> Option { + Some(LoadAccountResult::default()) + } + *) + Definition load_account (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_interpreter::host::LoadAccountResult", + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + (* + fn block_hash(&mut self, _number: U256) -> Option { + Some(B256::ZERO) + } + *) + Definition block_hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _number := M.alloc (| _number |) in + Value.StructTuple + "core::option::Option::Some" + [ M.read (| M.get_constant (| "alloy_primitives::bits::fixed::ZERO" |) |) ])) + | _, _ => M.impossible + end. + + (* + fn balance(&mut self, _address: Address) -> Option<(U256, bool)> { + Some((U256::ZERO, false)) + } + *) + Definition balance (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.Tuple [ M.read (| M.get_constant (| "ruint::ZERO" |) |); Value.Bool false ] + ])) + | _, _ => M.impossible + end. + + (* + fn code(&mut self, _address: Address) -> Option<(Bytecode, bool)> { + Some((Bytecode::default(), false)) + } + *) + Definition code (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + Value.StructTuple + "core::option::Option::Some" + [ + Value.Tuple + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "default", + [] + |), + [] + |); + Value.Bool false + ] + ])) + | _, _ => M.impossible + end. + + (* + fn code_hash(&mut self, __address: Address) -> Option<(B256, bool)> { + Some((KECCAK_EMPTY, false)) + } + *) + Definition code_hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; __address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let __address := M.alloc (| __address |) in + Value.StructTuple + "core::option::Option::Some" + [ + Value.Tuple + [ + M.read (| M.get_constant (| "revm_primitives::utilities::KECCAK_EMPTY" |) |); + Value.Bool false + ] + ])) + | _, _ => M.impossible + end. + + (* + fn sload(&mut self, __address: Address, index: U256) -> Option<(U256, bool)> { + match self.storage.entry(index) { + Entry::Occupied(entry) => Some(( *entry.get(), false)), + Entry::Vacant(entry) => { + entry.insert(U256::ZERO); + Some((U256::ZERO, true)) + } + } + } + *) + Definition sload (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; __address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let __address := M.alloc (| __address |) in + let index := M.alloc (| index |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "storage" + |); + M.read (| index |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.Tuple + [ + M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ], + "get", + [] + |), + [ entry ] + |) + |); + Value.Bool false + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ], + "insert", + [] + |), + [ M.read (| entry |); M.read (| M.get_constant (| "ruint::ZERO" |) |) ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.Tuple + [ M.read (| M.get_constant (| "ruint::ZERO" |) |); Value.Bool true ] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + (* + fn sstore(&mut self, _address: Address, index: U256, value: U256) -> Option { + let (present, is_cold) = match self.storage.entry(index) { + Entry::Occupied(mut entry) => (entry.insert(value), false), + Entry::Vacant(entry) => { + entry.insert(value); + (U256::ZERO, true) + } + }; + + Some(SStoreResult { + original_value: U256::ZERO, + present_value: present, + new_value: value, + is_cold, + }) + } + *) + Definition sstore (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _address; index; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + let index := M.alloc (| index |) in + let value := M.alloc (| value |) in + M.read (| + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "storage" + |); + M.read (| index |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.Tuple + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ], + "insert", + [] + |), + [ entry; M.read (| value |) ] + |); + Value.Bool false + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ], + "insert", + [] + |), + [ M.read (| entry |); M.read (| value |) ] + |) + |) in + M.alloc (| + Value.Tuple + [ M.read (| M.get_constant (| "ruint::ZERO" |) |); Value.Bool true ] + |))) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let present := M.copy (| ฮณ0_0 |) in + let is_cold := M.copy (| ฮณ0_1 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm_interpreter::host::SStoreResult" + [ + ("original_value", M.read (| M.get_constant (| "ruint::ZERO" |) |)); + ("present_value", M.read (| present |)); + ("new_value", M.read (| value |)); + ("is_cold", M.read (| is_cold |)) + ] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + (* + fn tload(&mut self, _address: Address, index: U256) -> U256 { + self.transient_storage + .get(&index) + .copied() + .unwrap_or_default() + } + *) + Definition tload (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ] ], + "copied", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "ruint::Uint" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "transient_storage" + |); + index + ] + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn tstore(&mut self, _address: Address, index: U256, value: U256) { + self.transient_storage.insert(index, value); + } + *) + Definition tstore (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _address; index; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + let index := M.alloc (| index |) in + let value := M.alloc (| value |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "transient_storage" + |); + M.read (| index |); + M.read (| value |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn log(&mut self, log: Log) { + self.log.push(log) + } + *) + Definition log (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; log ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let log := M.alloc (| log |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::host::dummy::DummyHost", + "log" + |); + M.read (| log |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn selfdestruct(&mut self, _address: Address, _target: Address) -> Option { + panic!("Selfdestruct is not supported for this host") + } + *) + Definition selfdestruct (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _address; _target ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + let _target := M.alloc (| _target |) in + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Arguments", "new_const", [] |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "Selfdestruct is not supported for this host" + |) + ] + |)) + ] + |) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "revm_interpreter::host::Host" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("env", InstanceField.Method env); + ("env_mut", InstanceField.Method env_mut); + ("load_account", InstanceField.Method load_account); + ("block_hash", InstanceField.Method block_hash); + ("balance", InstanceField.Method balance); + ("code", InstanceField.Method code); + ("code_hash", InstanceField.Method code_hash); + ("sload", InstanceField.Method sload); + ("sstore", InstanceField.Method sstore); + ("tload", InstanceField.Method tload); + ("tstore", InstanceField.Method tstore); + ("log", InstanceField.Method log); + ("selfdestruct", InstanceField.Method selfdestruct) + ]. + End Impl_revm_interpreter_host_Host_for_revm_interpreter_host_dummy_DummyHost. + End dummy. +End host. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instruction_result.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instruction_result.md new file mode 100644 index 00000000..3466e2f4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instruction_result.md @@ -0,0 +1,2794 @@ +# ๐Ÿ“ instruction_result.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instruction_result.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instruction_result. + (* + Enum InstructionResult + { + ty_params := []; + variants := + [ + { + name := "Continue"; + item := StructTuple []; + discriminant := Some 0; + }; + { + name := "Stop"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Return"; + item := StructTuple []; + discriminant := None; + }; + { + name := "SelfDestruct"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ReturnContract"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Revert"; + item := StructTuple []; + discriminant := Some 16; + }; + { + name := "CallTooDeep"; + item := StructTuple []; + discriminant := None; + }; + { + name := "OutOfFunds"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CallOrCreate"; + item := StructTuple []; + discriminant := Some 32; + }; + { + name := "OutOfGas"; + item := StructTuple []; + discriminant := Some 80; + }; + { + name := "MemoryOOG"; + item := StructTuple []; + discriminant := None; + }; + { + name := "MemoryLimitOOG"; + item := StructTuple []; + discriminant := None; + }; + { + name := "PrecompileOOG"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidOperandOOG"; + item := StructTuple []; + discriminant := None; + }; + { + name := "OpcodeNotFound"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CallNotAllowedInsideStatic"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StateChangeDuringStaticCall"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidFEOpcode"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidJump"; + item := StructTuple []; + discriminant := None; + }; + { + name := "NotActivated"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StackUnderflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StackOverflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "OutOfOffset"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CreateCollision"; + item := StructTuple []; + discriminant := None; + }; + { + name := "OverflowPayment"; + item := StructTuple []; + discriminant := None; + }; + { + name := "PrecompileError"; + item := StructTuple []; + discriminant := None; + }; + { + name := "NonceOverflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CreateContractSizeLimit"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CreateContractStartingWithEF"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CreateInitCodeSizeLimit"; + item := StructTuple []; + discriminant := None; + }; + { + name := "FatalExternalError"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ReturnContractInNotInitEOF"; + item := StructTuple []; + discriminant := None; + }; + { + name := "EOFOpcodeDisabledInLegacy"; + item := StructTuple []; + discriminant := None; + }; + { + name := "EOFFunctionStackOverflow"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_marker_Copy_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_fmt_Debug_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Continue" + |) in + M.alloc (| M.read (| Value.String "Continue" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Stop" + |) in + M.alloc (| M.read (| Value.String "Stop" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Return" + |) in + M.alloc (| M.read (| Value.String "Return" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + |) in + M.alloc (| M.read (| Value.String "SelfDestruct" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + M.alloc (| M.read (| Value.String "ReturnContract" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Revert" + |) in + M.alloc (| M.read (| Value.String "Revert" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + |) in + M.alloc (| M.read (| Value.String "CallTooDeep" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + |) in + M.alloc (| M.read (| Value.String "OutOfFunds" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + |) in + M.alloc (| M.read (| Value.String "CallOrCreate" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + |) in + M.alloc (| M.read (| Value.String "OutOfGas" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + |) in + M.alloc (| M.read (| Value.String "MemoryOOG" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::MemoryLimitOOG" + |) in + M.alloc (| M.read (| Value.String "MemoryLimitOOG" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::PrecompileOOG" + |) in + M.alloc (| M.read (| Value.String "PrecompileOOG" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + |) in + M.alloc (| M.read (| Value.String "InvalidOperandOOG" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OpcodeNotFound" + |) in + M.alloc (| M.read (| Value.String "OpcodeNotFound" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallNotAllowedInsideStatic" + |) in + M.alloc (| M.read (| Value.String "CallNotAllowedInsideStatic" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" + |) in + M.alloc (| M.read (| Value.String "StateChangeDuringStaticCall" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::InvalidFEOpcode" + |) in + M.alloc (| M.read (| Value.String "InvalidFEOpcode" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::InvalidJump" + |) in + M.alloc (| M.read (| Value.String "InvalidJump" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + |) in + M.alloc (| M.read (| Value.String "NotActivated" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + |) in + M.alloc (| M.read (| Value.String "StackUnderflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::StackOverflow" + |) in + M.alloc (| M.read (| Value.String "StackOverflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfOffset" + |) in + M.alloc (| M.read (| Value.String "OutOfOffset" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateCollision" + |) in + M.alloc (| M.read (| Value.String "CreateCollision" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OverflowPayment" + |) in + M.alloc (| M.read (| Value.String "OverflowPayment" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::PrecompileError" + |) in + M.alloc (| M.read (| Value.String "PrecompileError" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::NonceOverflow" + |) in + M.alloc (| M.read (| Value.String "NonceOverflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateContractSizeLimit" + |) in + M.alloc (| M.read (| Value.String "CreateContractSizeLimit" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateContractStartingWithEF" + |) in + M.alloc (| M.read (| Value.String "CreateContractStartingWithEF" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateInitCodeSizeLimit" + |) in + M.alloc (| M.read (| Value.String "CreateInitCodeSizeLimit" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::FatalExternalError" + |) in + M.alloc (| M.read (| Value.String "FatalExternalError" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContractInNotInitEOF" + |) in + M.alloc (| M.read (| Value.String "ReturnContractInNotInitEOF" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + |) in + M.alloc (| M.read (| Value.String "EOFOpcodeDisabledInLegacy" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::EOFFunctionStackOverflow" + |) in + M.alloc (| M.read (| Value.String "EOFFunctionStackOverflow" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_default_Default_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Continue" + [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instruction_result::InstructionResult" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instruction_result::InstructionResult" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_cmp_Eq_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_hash_Hash_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instruction_result::InstructionResult" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u8", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_convert_From_revm_primitives_result_SuccessReason_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + (* + fn from(value: SuccessReason) -> Self { + match value { + SuccessReason::Return => InstructionResult::Return, + SuccessReason::Stop => InstructionResult::Stop, + SuccessReason::SelfDestruct => InstructionResult::SelfDestruct, + } + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + M.read (| + M.match_operator (| + value, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::result::SuccessReason::Return" |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Return" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::result::SuccessReason::Stop" |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Stop" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::SuccessReason::SelfDestruct" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + [] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) [ (* T *) Ty.path "revm_primitives::result::SuccessReason" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_primitives_result_SuccessReason_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_core_convert_From_revm_primitives_result_HaltReason_for_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + (* + fn from(value: HaltReason) -> Self { + match value { + HaltReason::OutOfGas(error) => match error { + OutOfGasError::Basic => Self::OutOfGas, + OutOfGasError::InvalidOperand => Self::InvalidOperandOOG, + OutOfGasError::Memory => Self::MemoryOOG, + OutOfGasError::MemoryLimit => Self::MemoryLimitOOG, + OutOfGasError::Precompile => Self::PrecompileOOG, + }, + HaltReason::OpcodeNotFound => Self::OpcodeNotFound, + HaltReason::InvalidFEOpcode => Self::InvalidFEOpcode, + HaltReason::InvalidJump => Self::InvalidJump, + HaltReason::NotActivated => Self::NotActivated, + HaltReason::StackOverflow => Self::StackOverflow, + HaltReason::StackUnderflow => Self::StackUnderflow, + HaltReason::OutOfOffset => Self::OutOfOffset, + HaltReason::CreateCollision => Self::CreateCollision, + HaltReason::PrecompileError => Self::PrecompileError, + HaltReason::NonceOverflow => Self::NonceOverflow, + HaltReason::CreateContractSizeLimit => Self::CreateContractSizeLimit, + HaltReason::CreateContractStartingWithEF => Self::CreateContractStartingWithEF, + HaltReason::CreateInitCodeSizeLimit => Self::CreateInitCodeSizeLimit, + HaltReason::OverflowPayment => Self::OverflowPayment, + HaltReason::StateChangeDuringStaticCall => Self::StateChangeDuringStaticCall, + HaltReason::CallNotAllowedInsideStatic => Self::CallNotAllowedInsideStatic, + HaltReason::OutOfFunds => Self::OutOfFunds, + HaltReason::CallTooDeep => Self::CallTooDeep, + #[cfg(feature = "optimism")] + HaltReason::FailedDeposit => Self::FatalExternalError, + } + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + M.read (| + M.match_operator (| + value, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::HaltReason::OutOfGas", + 0 + |) in + let error := M.copy (| ฮณ0_0 |) in + M.match_operator (| + error, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::Basic" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::InvalidOperand" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::Memory" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::MemoryLimit" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryLimitOOG" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::Precompile" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::PrecompileOOG" + [] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::OpcodeNotFound" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OpcodeNotFound" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::InvalidFEOpcode" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidFEOpcode" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::InvalidJump" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidJump" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::NotActivated" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::StackOverflow" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackOverflow" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::StackUnderflow" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::OutOfOffset" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfOffset" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CreateCollision" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CreateCollision" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::PrecompileError" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::PrecompileError" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::NonceOverflow" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NonceOverflow" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CreateContractSizeLimit" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CreateContractSizeLimit" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CreateContractStartingWithEF" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CreateContractStartingWithEF" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CreateInitCodeSizeLimit" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CreateInitCodeSizeLimit" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::OverflowPayment" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OverflowPayment" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::StateChangeDuringStaticCall" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CallNotAllowedInsideStatic" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallNotAllowedInsideStatic" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::OutOfFunds" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CallTooDeep" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + [] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) [ (* T *) Ty.path "revm_primitives::result::HaltReason" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_primitives_result_HaltReason_for_revm_interpreter_instruction_result_InstructionResult. + + Module Impl_revm_interpreter_instruction_result_InstructionResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::InstructionResult". + + (* + pub const fn is_ok(self) -> bool { + matches!(self, crate::return_ok!()) + } + *) + Definition is_ok (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Continue" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Stop" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Return" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_ok : M.IsAssociatedFunction Self "is_ok" is_ok. + + (* + pub const fn is_revert(self) -> bool { + matches!(self, crate::return_revert!()) + } + *) + Definition is_revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Revert" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_revert : M.IsAssociatedFunction Self "is_revert" is_revert. + + (* + pub const fn is_error(self) -> bool { + matches!(self, return_error!()) + } + *) + Definition is_error (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::MemoryLimitOOG" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::PrecompileOOG" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OpcodeNotFound" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallNotAllowedInsideStatic" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::InvalidFEOpcode" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::InvalidJump" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::StackOverflow" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfOffset" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateCollision" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OverflowPayment" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::PrecompileError" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::NonceOverflow" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateContractSizeLimit" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateContractStartingWithEF" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateInitCodeSizeLimit" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::FatalExternalError" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContractInNotInitEOF" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::EOFFunctionStackOverflow" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_error : M.IsAssociatedFunction Self "is_error" is_error. + End Impl_revm_interpreter_instruction_result_InstructionResult. + + (* + Enum SuccessOrHalt + { + ty_params := []; + variants := + [ + { + name := "Success"; + item := StructTuple [ Ty.path "revm_primitives::result::SuccessReason" ]; + discriminant := None; + }; + { + name := "Revert"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Halt"; + item := StructTuple [ Ty.path "revm_primitives::result::HaltReason" ]; + discriminant := None; + }; + { + name := "FatalExternalError"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InternalContinue"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InternalCallOrCreate"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Success", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Success" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Revert" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Revert" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Halt", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Halt" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::FatalExternalError" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "FatalExternalError" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::InternalContinue" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "InternalContinue" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::InternalCallOrCreate" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "InternalCallOrCreate" |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_instruction_result_SuccessOrHalt. + + Module Impl_core_marker_Copy_for_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_instruction_result_SuccessOrHalt. + + Module Impl_core_clone_Clone_for_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_instruction_result_SuccessOrHalt. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_instruction_result_SuccessOrHalt. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instruction_result::SuccessOrHalt" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instruction_result::SuccessOrHalt" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::instruction_result::SuccessOrHalt::Success", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::instruction_result::SuccessOrHalt::Success", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::result::SuccessReason", + [ Ty.path "revm_primitives::result::SuccessReason" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::instruction_result::SuccessOrHalt::Halt", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::instruction_result::SuccessOrHalt::Halt", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::result::HaltReason", + [ Ty.path "revm_primitives::result::HaltReason" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool true |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_instruction_result_SuccessOrHalt. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_instruction_result_SuccessOrHalt. + + Module Impl_core_cmp_Eq_for_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_instruction_result_SuccessOrHalt. + + Module Impl_core_hash_Hash_for_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instruction_result::SuccessOrHalt" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Success", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::result::SuccessReason", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Halt", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::result::HaltReason", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_instruction_result_SuccessOrHalt. + + Module Impl_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + (* + pub fn is_success(self) -> bool { + matches!(self, SuccessOrHalt::Success(_)) + } + *) + Definition is_success (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Success", + 0 + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_success : M.IsAssociatedFunction Self "is_success" is_success. + + (* + pub fn to_success(self) -> Option { + match self { + SuccessOrHalt::Success(reason) => Some(reason), + _ => None, + } + } + *) + Definition to_success (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Success", + 0 + |) in + let reason := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| reason |) ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_to_success : M.IsAssociatedFunction Self "to_success" to_success. + + (* + pub fn is_revert(self) -> bool { + matches!(self, SuccessOrHalt::Revert) + } + *) + Definition is_revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Revert" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_revert : M.IsAssociatedFunction Self "is_revert" is_revert. + + (* + pub fn is_halt(self) -> bool { + matches!(self, SuccessOrHalt::Halt(_)) + } + *) + Definition is_halt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Halt", + 0 + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_halt : M.IsAssociatedFunction Self "is_halt" is_halt. + + (* + pub fn to_halt(self) -> Option { + match self { + SuccessOrHalt::Halt(reason) => Some(reason), + _ => None, + } + } + *) + Definition to_halt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Halt", + 0 + |) in + let reason := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| reason |) ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_to_halt : M.IsAssociatedFunction Self "to_halt" to_halt. + End Impl_revm_interpreter_instruction_result_SuccessOrHalt. + + Module Impl_core_convert_From_revm_interpreter_instruction_result_InstructionResult_for_revm_interpreter_instruction_result_SuccessOrHalt. + Definition Self : Ty.t := Ty.path "revm_interpreter::instruction_result::SuccessOrHalt". + + (* + fn from(result: InstructionResult) -> Self { + match result { + InstructionResult::Continue => Self::InternalContinue, // used only in interpreter loop + InstructionResult::Stop => Self::Success(SuccessReason::Stop), + InstructionResult::Return => Self::Success(SuccessReason::Return), + InstructionResult::SelfDestruct => Self::Success(SuccessReason::SelfDestruct), + InstructionResult::Revert => Self::Revert, + InstructionResult::CallOrCreate => Self::InternalCallOrCreate, // used only in interpreter loop + InstructionResult::CallTooDeep => Self::Halt(HaltReason::CallTooDeep), // not gonna happen for first call + InstructionResult::OutOfFunds => Self::Halt(HaltReason::OutOfFunds), // Check for first call is done separately. + InstructionResult::OutOfGas => Self::Halt(HaltReason::OutOfGas(OutOfGasError::Basic)), + InstructionResult::MemoryLimitOOG => { + Self::Halt(HaltReason::OutOfGas(OutOfGasError::MemoryLimit)) + } + InstructionResult::MemoryOOG => Self::Halt(HaltReason::OutOfGas(OutOfGasError::Memory)), + InstructionResult::PrecompileOOG => { + Self::Halt(HaltReason::OutOfGas(OutOfGasError::Precompile)) + } + InstructionResult::InvalidOperandOOG => { + Self::Halt(HaltReason::OutOfGas(OutOfGasError::InvalidOperand)) + } + InstructionResult::OpcodeNotFound | InstructionResult::ReturnContractInNotInitEOF => { + Self::Halt(HaltReason::OpcodeNotFound) + } + InstructionResult::CallNotAllowedInsideStatic => { + Self::Halt(HaltReason::CallNotAllowedInsideStatic) + } // first call is not static call + InstructionResult::StateChangeDuringStaticCall => { + Self::Halt(HaltReason::StateChangeDuringStaticCall) + } + InstructionResult::InvalidFEOpcode => Self::Halt(HaltReason::InvalidFEOpcode), + InstructionResult::InvalidJump => Self::Halt(HaltReason::InvalidJump), + InstructionResult::NotActivated => Self::Halt(HaltReason::NotActivated), + InstructionResult::StackUnderflow => Self::Halt(HaltReason::StackUnderflow), + InstructionResult::StackOverflow => Self::Halt(HaltReason::StackOverflow), + InstructionResult::OutOfOffset => Self::Halt(HaltReason::OutOfOffset), + InstructionResult::CreateCollision => Self::Halt(HaltReason::CreateCollision), + InstructionResult::OverflowPayment => Self::Halt(HaltReason::OverflowPayment), // Check for first call is done separately. + InstructionResult::PrecompileError => Self::Halt(HaltReason::PrecompileError), + InstructionResult::NonceOverflow => Self::Halt(HaltReason::NonceOverflow), + InstructionResult::CreateContractSizeLimit + | InstructionResult::CreateContractStartingWithEF => { + Self::Halt(HaltReason::CreateContractSizeLimit) + } + InstructionResult::CreateInitCodeSizeLimit => { + Self::Halt(HaltReason::CreateInitCodeSizeLimit) + } + InstructionResult::FatalExternalError => Self::FatalExternalError, + InstructionResult::EOFOpcodeDisabledInLegacy => Self::Halt(HaltReason::OpcodeNotFound), + InstructionResult::EOFFunctionStackOverflow => Self::FatalExternalError, + InstructionResult::ReturnContract => { + panic!("Unexpected EOF internal Return Contract") + } + } + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ result ] => + ltac:(M.monadic + (let result := M.alloc (| result |) in + M.read (| + M.match_operator (| + result, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Continue" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::InternalContinue" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Stop" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Success" + [ Value.StructTuple "revm_primitives::result::SuccessReason::Stop" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Return" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Success" + [ Value.StructTuple "revm_primitives::result::SuccessReason::Return" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Success" + [ + Value.StructTuple + "revm_primitives::result::SuccessReason::SelfDestruct" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Revert" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Revert" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::InternalCallOrCreate" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ Value.StructTuple "revm_primitives::result::HaltReason::CallTooDeep" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ Value.StructTuple "revm_primitives::result::HaltReason::OutOfFunds" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::OutOfGas" + [ Value.StructTuple "revm_primitives::result::OutOfGasError::Basic" [] ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::MemoryLimitOOG" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::OutOfGas" + [ + Value.StructTuple + "revm_primitives::result::OutOfGasError::MemoryLimit" + [] + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::OutOfGas" + [ Value.StructTuple "revm_primitives::result::OutOfGasError::Memory" [] + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::PrecompileOOG" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::OutOfGas" + [ + Value.StructTuple + "revm_primitives::result::OutOfGasError::Precompile" + [] + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::OutOfGas" + [ + Value.StructTuple + "revm_primitives::result::OutOfGasError::InvalidOperand" + [] + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OpcodeNotFound" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContractInNotInitEOF" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::OpcodeNotFound" + [] + ] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallNotAllowedInsideStatic" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::CallNotAllowedInsideStatic" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::StateChangeDuringStaticCall" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::InvalidFEOpcode" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::InvalidFEOpcode" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::InvalidJump" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ Value.StructTuple "revm_primitives::result::HaltReason::InvalidJump" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ Value.StructTuple "revm_primitives::result::HaltReason::NotActivated" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ Value.StructTuple "revm_primitives::result::HaltReason::StackUnderflow" [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::StackOverflow" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ Value.StructTuple "revm_primitives::result::HaltReason::StackOverflow" [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfOffset" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ Value.StructTuple "revm_primitives::result::HaltReason::OutOfOffset" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateCollision" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::CreateCollision" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OverflowPayment" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::OverflowPayment" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::PrecompileError" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::PrecompileError" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::NonceOverflow" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ Value.StructTuple "revm_primitives::result::HaltReason::NonceOverflow" [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateContractSizeLimit" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateContractStartingWithEF" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::CreateContractSizeLimit" + [] + ] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CreateInitCodeSizeLimit" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ + Value.StructTuple + "revm_primitives::result::HaltReason::CreateInitCodeSizeLimit" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::FatalExternalError" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::FatalExternalError" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::Halt" + [ Value.StructTuple "revm_primitives::result::HaltReason::OpcodeNotFound" [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::EOFFunctionStackOverflow" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::SuccessOrHalt::FatalExternalError" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "Unexpected EOF internal Return Contract" + |) + ] + |)) + ] + |) + ] + |) + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ (* T *) Ty.path "revm_interpreter::instruction_result::InstructionResult" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_interpreter_instruction_result_InstructionResult_for_revm_interpreter_instruction_result_SuccessOrHalt. +End instruction_result. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/arithmetic.md new file mode 100644 index 00000000..53ade3d9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/arithmetic.md @@ -0,0 +1,2061 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/arithmetic.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module arithmetic. + (* + pub fn add(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1.wrapping_add( *op2); + } + *) + Definition add (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_add", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_add : M.IsFunction "revm_interpreter::instructions::arithmetic::add" add. + + (* + pub fn mul(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + *op2 = op1.wrapping_mul( *op2); + } + *) + Definition mul (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOW" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_mul", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_mul : M.IsFunction "revm_interpreter::instructions::arithmetic::mul" mul. + + (* + pub fn sub(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1.wrapping_sub( *op2); + } + *) + Definition sub (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_sub", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sub : M.IsFunction "revm_interpreter::instructions::arithmetic::sub" sub. + + (* + pub fn div(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + if *op2 != U256::ZERO { + *op2 = op1.wrapping_div( *op2); + } + } + *) + Definition div (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOW" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ M.read (| op2 |); M.get_constant (| "ruint::ZERO" |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_div", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_div : M.IsFunction "revm_interpreter::instructions::arithmetic::div" div. + + (* + pub fn sdiv(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + *op2 = i256_div(op1, *op2); + } + *) + Definition sdiv (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOW" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::i256_div", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sdiv : M.IsFunction "revm_interpreter::instructions::arithmetic::sdiv" sdiv. + + (* + pub fn rem(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + if *op2 != U256::ZERO { + *op2 = op1.wrapping_rem( *op2); + } + } + *) + Definition rem (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOW" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ M.read (| op2 |); M.get_constant (| "ruint::ZERO" |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_rem", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_rem : M.IsFunction "revm_interpreter::instructions::arithmetic::rem" rem. + + (* + pub fn smod(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + *op2 = i256_mod(op1, *op2) + } + *) + Definition smod (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOW" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::i256_mod", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_smod : M.IsFunction "revm_interpreter::instructions::arithmetic::smod" smod. + + (* + pub fn addmod(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::MID); + pop_top!(interpreter, op1, op2, op3); + *op3 = op1.add_mod(op2, *op3) + } + *) + Definition addmod (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::MID" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 3) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let op3 := M.copy (| ฮณ0_2 |) in + M.write (| + M.read (| op3 |), + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "add_mod", [] |), + [ M.read (| op1 |); M.read (| op2 |); M.read (| M.read (| op3 |) |) ] + |) + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_addmod : + M.IsFunction "revm_interpreter::instructions::arithmetic::addmod" addmod. + + (* + pub fn mulmod(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::MID); + pop_top!(interpreter, op1, op2, op3); + *op3 = op1.mul_mod(op2, *op3) + } + *) + Definition mulmod (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::MID" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 3) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let op3 := M.copy (| ฮณ0_2 |) in + M.write (| + M.read (| op3 |), + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "mul_mod", [] |), + [ M.read (| op1 |); M.read (| op2 |); M.read (| M.read (| op3 |) |) ] + |) + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_mulmod : + M.IsFunction "revm_interpreter::instructions::arithmetic::mulmod" mulmod. + + (* + pub fn exp(interpreter: &mut Interpreter, _host: &mut H) { + pop_top!(interpreter, op1, op2); + gas_or_fail!(interpreter, gas::exp_cost(SPEC::SPEC_ID, *op2)); + *op2 = op1.pow( *op2); + } + *) + Definition exp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::exp_cost", [] |), + [ + M.read (| + M.get_constant (| + "revm_primitives::specification::Spec::SPEC_ID" + |) + |); + M.read (| M.read (| op2 |) |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "pow", [] |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_exp : M.IsFunction "revm_interpreter::instructions::arithmetic::exp" exp. + + (* + pub fn signextend(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, ext, x); + // For 31 we also don't need to do anything. + if ext < U256::from(31) { + let ext = ext.as_limbs()[0]; + let bit_index = (8 * ext + 7) as usize; + let bit = x.bit(bit_index); + let mask = (U256::from(1) << bit_index) - U256::from(1); + *x = if bit { *x | !mask } else { *x & mask }; + } + } + *) + Definition signextend (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOW" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ext := M.copy (| ฮณ0_0 |) in + let x := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "lt", + [] + |), + [ + ext; + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 31 ] + |) + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ ext := + M.copy (| + M.SubPointer.get_array_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ ext ] + |), + M.alloc (| Value.Integer 0 |) + |) + |) in + let~ bit_index := + M.alloc (| + M.rust_cast + (BinOp.Wrap.add + Integer.U64 + (BinOp.Wrap.mul + Integer.U64 + (Value.Integer 8) + (M.read (| ext |))) + (Value.Integer 7)) + |) in + let~ bit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "bit", + [] + |), + [ M.read (| x |); M.read (| bit_index |) ] + |) + |) in + let~ mask := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Sub", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "sub", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::Shl", + Ty.path "ruint::Uint", + [ Ty.path "usize" ], + "shl", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 1 ] + |); + M.read (| bit_index |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 1 ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| x |), + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use bit in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::BitOr", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "bitor", + [] + |), + [ + M.read (| M.read (| x |) |); + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::Not", + Ty.path "ruint::Uint", + [], + "not", + [] + |), + [ M.read (| mask |) ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::BitAnd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "bitand", + [] + |), + [ M.read (| M.read (| x |) |); M.read (| mask |) ] + |) + |))) + ] + |) + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_signextend : + M.IsFunction "revm_interpreter::instructions::arithmetic::signextend" signextend. + End arithmetic. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/bitwise.md new file mode 100644 index 00000000..5329b11f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/bitwise.md @@ -0,0 +1,3135 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/bitwise.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module bitwise. + (* + pub fn lt(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(op1 < *op2); + } + *) + Definition lt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "bool" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "lt", + [] + |), + [ op1; M.read (| op2 |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_lt : M.IsFunction "revm_interpreter::instructions::bitwise::lt" lt. + + (* + pub fn gt(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(op1 > *op2); + } + *) + Definition gt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "bool" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "gt", + [] + |), + [ op1; M.read (| op2 |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_gt : M.IsFunction "revm_interpreter::instructions::bitwise::gt" gt. + + (* + pub fn slt(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less); + } + *) + Definition slt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "bool" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "core::cmp::Ordering", + [ Ty.path "core::cmp::Ordering" ], + "eq", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::i256_cmp", + [] + |), + [ op1; M.read (| op2 |) ] + |) + |); + M.alloc (| Value.StructTuple "core::cmp::Ordering::Less" [] |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_slt : M.IsFunction "revm_interpreter::instructions::bitwise::slt" slt. + + (* + pub fn sgt(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater); + } + *) + Definition sgt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "bool" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "core::cmp::Ordering", + [ Ty.path "core::cmp::Ordering" ], + "eq", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::i256_cmp", + [] + |), + [ op1; M.read (| op2 |) ] + |) + |); + M.alloc (| + Value.StructTuple "core::cmp::Ordering::Greater" [] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sgt : M.IsFunction "revm_interpreter::instructions::bitwise::sgt" sgt. + + (* + pub fn eq(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(op1 == *op2); + } + *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "bool" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ op1; M.read (| op2 |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_eq : M.IsFunction "revm_interpreter::instructions::bitwise::eq" eq. + + (* + pub fn iszero(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1); + *op1 = U256::from( *op1 == U256::ZERO); + } + *) + Definition iszero (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ op1 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| op1 |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "bool" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| op1 |); M.get_constant (| "ruint::ZERO" |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_iszero : M.IsFunction "revm_interpreter::instructions::bitwise::iszero" iszero. + + (* + pub fn bitand(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1 & *op2; + } + *) + Definition bitand (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::BitAnd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "bitand", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_bitand : M.IsFunction "revm_interpreter::instructions::bitwise::bitand" bitand. + + (* + pub fn bitor(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1 | *op2; + } + *) + Definition bitor (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::BitOr", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "bitor", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_bitor : M.IsFunction "revm_interpreter::instructions::bitwise::bitor" bitor. + + (* + pub fn bitxor(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1 ^ *op2; + } + *) + Definition bitxor (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::BitXor", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "bitxor", + [] + |), + [ M.read (| op1 |); M.read (| M.read (| op2 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_bitxor : M.IsFunction "revm_interpreter::instructions::bitwise::bitxor" bitxor. + + (* + pub fn not(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1); + *op1 = !*op1; + } + *) + Definition not (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ op1 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| op1 |), + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::Not", + Ty.path "ruint::Uint", + [], + "not", + [] + |), + [ M.read (| M.read (| op1 |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_not : M.IsFunction "revm_interpreter::instructions::bitwise::not" not. + + (* + pub fn byte(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + + let o1 = as_usize_saturated!(op1); + *op2 = if o1 < 32 { + // `31 - o1` because `byte` returns LE, while we want BE + U256::from(op2.byte(31 - o1)) + } else { + U256::ZERO + }; + } + *) + Definition byte (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ o1 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ op1 ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => + ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt (M.read (| o1 |)) (Value.Integer 32) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u8" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "byte", + [] + |), + [ + M.read (| op2 |); + BinOp.Wrap.sub + Integer.Usize + (Value.Integer 31) + (M.read (| o1 |)) + ] + |) + ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.get_constant (| "ruint::ZERO" |))) + ] + |) + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_byte : M.IsFunction "revm_interpreter::instructions::bitwise::byte" byte. + + (* + pub fn shl(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, CONSTANTINOPLE); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 <<= as_usize_saturated!(op1); + } + *) + Definition shl (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CONSTANTINOPLE" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::ShlAssign", + Ty.path "ruint::Uint", + [ Ty.path "usize" ], + "shl_assign", + [] + |), + [ + M.read (| op2 |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" + ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ op1 ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_shl : M.IsFunction "revm_interpreter::instructions::bitwise::shl" shl. + + (* + pub fn shr(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, CONSTANTINOPLE); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 >>= as_usize_saturated!(op1); + } + *) + Definition shr (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CONSTANTINOPLE" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::ShrAssign", + Ty.path "ruint::Uint", + [ Ty.path "usize" ], + "shr_assign", + [] + |), + [ + M.read (| op2 |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" + ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ op1 ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_shr : M.IsFunction "revm_interpreter::instructions::bitwise::shr" shr. + + (* + pub fn sar(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, CONSTANTINOPLE); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + + let value_sign = i256_sign_compl(op2); + + // If the shift count is 255+, we can short-circuit. This is because shifting by 255 bits is the + // maximum shift that still leaves 1 bit in the original 256-bit number. Shifting by 256 bits or + // more would mean that no original bits remain. The result depends on what the highest bit of + // the value is. + *op2 = if value_sign == Sign::Zero || op1 >= U256::from(255) { + match value_sign { + // value is 0 or >=1, pushing 0 + Sign::Plus | Sign::Zero => U256::ZERO, + // value is <0, pushing -1 + Sign::Minus => U256::MAX, + } + } else { + const ONE: U256 = uint!(1_U256); + // SAFETY: shift count is checked above; it's less than 255. + let shift = usize::try_from(op1).unwrap(); + match value_sign { + Sign::Plus | Sign::Zero => op2.wrapping_shr(shift), + Sign::Minus => two_compl(op2.wrapping_sub(ONE).wrapping_shr(shift).wrapping_add(ONE)), + } + }; + } + *) + Definition sar (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CONSTANTINOPLE" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let op1 := M.copy (| ฮณ0_0 |) in + let op2 := M.copy (| ฮณ0_1 |) in + let~ value_sign := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::i256_sign_compl", + [] + |), + [ M.read (| op2 |) ] + |) + |) in + let~ _ := + M.write (| + M.read (| op2 |), + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "revm_interpreter::instructions::i256::Sign", + [ + Ty.path + "revm_interpreter::instructions::i256::Sign" + ], + "eq", + [] + |), + [ + value_sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Zero" + [] + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ge", + [] + |), + [ + op1; + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 255 ] + |) + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + value_sign, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instructions::i256::Sign::Plus" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instructions::i256::Sign::Zero" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.get_constant (| "ruint::ZERO" |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instructions::i256::Sign::Minus" + |) in + M.get_constant (| "ruint::MAX" |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ shift := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "usize"; + Ty.apply + (Ty.path "ruint::from::FromUintError") + [ Ty.path "usize" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ M.read (| op1 |) ] + |) + ] + |) + |) in + M.match_operator (| + value_sign, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instructions::i256::Sign::Plus" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instructions::i256::Sign::Zero" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_shr", + [] + |), + [ + M.read (| M.read (| op2 |) |); + M.read (| shift |) + ] + |) + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instructions::i256::Sign::Minus" + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::two_compl", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_shr", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_sub", + [] + |), + [ + M.read (| M.read (| op2 |) |); + M.read (| + M.get_constant (| + "revm_interpreter::instructions::bitwise::sar::ONE" + |) + |) + ] + |); + M.read (| shift |) + ] + |); + M.read (| + M.get_constant (| + "revm_interpreter::instructions::bitwise::sar::ONE" + |) + |) + ] + |) + ] + |) + |))) + ] + |))) + ] + |) + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sar : M.IsFunction "revm_interpreter::instructions::bitwise::sar" sar. + + Module sar. + Definition value_ONE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from_limbs", [] |), + [ Value.Array [ Value.Integer 1; Value.Integer 0; Value.Integer 0; Value.Integer 0 ] + ] + |) + |))). + End sar. + End bitwise. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/contract.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/contract.md new file mode 100644 index 00000000..0bbb2cae --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/contract.md @@ -0,0 +1,8422 @@ +# ๐Ÿ“ contract.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/contract.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module contract. + (* + pub fn resize_memory( + interpreter: &mut Interpreter, + offset: U256, + len: U256, + ) -> Option> { + let len = as_usize_or_fail_ret!(interpreter, len, None); + if len != 0 { + let offset = as_usize_or_fail_ret!(interpreter, offset, None); + resize_memory!(interpreter, offset, len, None); + // range is checked in resize_memory! macro and it is bounded by usize. + Some(offset..offset + len) + } else { + //unrealistic value so we are sure it is not used + Some(usize::MAX..usize::MAX) + } + } + *) + Definition resize_memory (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ interpreter; offset; len ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let offset := M.alloc (| offset |) in + let len := M.alloc (| len |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "as_limbs", [] |), + [ len ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| BinOp.Pure.ne (M.read (| len |)) (Value.Integer 0) |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "usize", "saturating_add", [] |), + [ M.read (| offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| offset |)); + ("end_", + BinOp.Wrap.add + Integer.Usize + (M.read (| offset |)) + (M.read (| len |))) + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| M.get_constant (| "core::num::MAX" |) |)); + ("end_", M.read (| M.get_constant (| "core::num::MAX" |) |)) + ] + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_resize_memory : + M.IsFunction "revm_interpreter::instructions::contract::resize_memory" resize_memory. + + (* + pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, EOF_CREATE_GAS); + let initcontainer_index = unsafe { *interpreter.instruction_pointer }; + pop!(interpreter, value, salt, data_offset, data_size); + + let sub_container = interpreter + .eof() + .expect("EOF is set") + .body + .container_section + .get(initcontainer_index as usize) + .cloned() + .expect("EOF is checked"); + + // resize memory and get return range. + let Some(return_range) = resize_memory(interpreter, data_offset, data_size) else { + return; + }; + + let eof = Eof::decode(sub_container.clone()).expect("Subcontainer is verified"); + + if !eof.body.is_data_filled { + // should be always false as it is verified by eof verification. + panic!("Panic if data section is not full"); + } + + // deduct gas for hash that is needed to calculate address. + gas_or_fail!( + interpreter, + cost_per_word(sub_container.len() as u64, KECCAK256WORD) + ); + + let created_address = interpreter + .contract + .caller + .create2(salt.to_be_bytes(), keccak256(sub_container)); + + // Send container for execution container is preverified. + interpreter.next_action = InterpreterAction::EOFCreate { + inputs: Box::new(EOFCreateInput::new( + interpreter.contract.target_address, + created_address, + value, + eof, + interpreter.gas().remaining(), + return_range, + )), + }; + + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) }; + } + *) + Definition eofcreate (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::EOF_CREATE_GAS" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ initcontainer_index := + M.copy (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 4) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop4_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let ฮณ0_3 := M.SubPointer.get_tuple_field (| ฮณ, 3 |) in + let value := M.copy (| ฮณ0_0 |) in + let salt := M.copy (| ฮณ0_1 |) in + let data_offset := M.copy (| ฮณ0_2 |) in + let data_size := M.copy (| ฮณ0_3 |) in + let~ sub_container := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ], + "cloned", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "get", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::bytecode::eof::Eof" + ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::Interpreter", + "eof", + [] + |), + [ M.read (| interpreter |) ] + |); + M.read (| Value.String "EOF is set" |) + ] + |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |) + ] + |); + M.rust_cast (M.read (| initcontainer_index |)) + ] + |) + ] + |); + M.read (| Value.String "EOF is checked" |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::resize_memory", + [] + |), + [ + M.read (| interpreter |); + M.read (| data_offset |); + M.read (| data_size |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let return_range := M.copy (| ฮณ0_0 |) in + let~ eof := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::eof::Eof"; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "decode", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ sub_container ] + |) + ] + |); + M.read (| Value.String "Subcontainer is verified" |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + eof, + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "is_data_filled" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic_fmt", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "Panic if data section is not full" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::cost_per_word", + [] + |), + [ + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ sub_container ] + |) + ] + |)); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::KECCAK256WORD" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ created_address := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "create2", + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "alloy_primitives::bits::fixed::FixedBytes" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "caller" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "to_be_bytes", + [] + |), + [ salt ] + |); + M.call_closure (| + M.get_function (| + "alloy_primitives::utils::keccak256", + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + |), + [ M.read (| sub_container |) ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |); + M.read (| created_address |); + M.read (| value |); + M.read (| eof |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::Interpreter", + "gas", + [] + |), + [ M.read (| interpreter |) ] + |) + ] + |); + M.read (| return_range |) + ] + |) + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + Value.Integer 1 + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_eofcreate : + M.IsFunction "revm_interpreter::instructions::contract::eofcreate" eofcreate. + + (* + pub fn txcreate(interpreter: &mut Interpreter, host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, EOF_CREATE_GAS); + pop!( + interpreter, + tx_initcode_hash, + value, + salt, + data_offset, + data_size + ); + let tx_initcode_hash = B256::from(tx_initcode_hash); + + // resize memory and get return range. + let Some(return_range) = resize_memory(interpreter, data_offset, data_size) else { + return; + }; + + // fetch initcode, if not found push ZERO. + let Some(initcode) = host + .env() + .tx + .eof_initcodes_hashed + .get(&tx_initcode_hash) + .cloned() + else { + push!(interpreter, U256::ZERO); + return; + }; + + // deduct gas for validation + gas_or_fail!(interpreter, cost_per_word(initcode.len() as u64, BASE)); + + // deduct gas for hash. TODO check order of actions. + gas_or_fail!( + interpreter, + cost_per_word(initcode.len() as u64, KECCAK256WORD) + ); + + let Ok(eof) = Eof::decode(initcode.clone()) else { + push!(interpreter, U256::ZERO); + return; + }; + + // Data section should be full, push zero to stack and return if not. + if !eof.body.is_data_filled { + push!(interpreter, U256::ZERO); + return; + } + + // Validate initcode + if validate_eof(&eof).is_err() { + push!(interpreter, U256::ZERO); + return; + } + + // Create new address. Gas for it is already deducted. + let created_address = interpreter + .contract + .caller + .create2(salt.to_be_bytes(), tx_initcode_hash); + + let gas_limit = interpreter.gas().remaining(); + // spend all gas. It will be reimbursed after frame returns. + gas!(interpreter, gas_limit); + + interpreter.next_action = InterpreterAction::EOFCreate { + inputs: Box::new(EOFCreateInput::new( + interpreter.contract.target_address, + created_address, + value, + eof, + gas_limit, + return_range, + )), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; + } + *) + Definition txcreate (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::EOF_CREATE_GAS" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 4) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop5_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let ฮณ0_3 := M.SubPointer.get_tuple_field (| ฮณ, 3 |) in + let ฮณ0_4 := M.SubPointer.get_tuple_field (| ฮณ, 4 |) in + let tx_initcode_hash := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + let salt := M.copy (| ฮณ0_2 |) in + let data_offset := M.copy (| ฮณ0_3 |) in + let data_size := M.copy (| ฮณ0_4 |) in + let~ tx_initcode_hash := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ M.read (| tx_initcode_hash |) ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::resize_memory", + [] + |), + [ + M.read (| interpreter |); + M.read (| data_offset |); + M.read (| data_size |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let return_range := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ], + "cloned", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "eof_initcodes_hashed" + |); + tx_initcode_hash + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let initcode := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::cost_per_word", + [] + |), + [ + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path + "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ initcode ] + |) + ] + |)); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::cost_per_word", + [] + |), + [ + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path + "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ initcode ] + |) + ] + |)); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::KECCAK256WORD" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "decode", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ initcode ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let eof := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + eof, + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "is_data_filled" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + interpreter + |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.get_constant (| + "ruint::ZERO" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| + Value.Tuple [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := + M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| + interpreter + |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| + Value.Tuple [] + |) + |) + |) + |))) + ] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_interpreter::interpreter::analysis::EofError" + ], + "is_err", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::analysis::validate_eof", + [] + |), + [ eof ] + |) + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + interpreter + |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.get_constant (| + "ruint::ZERO" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| + Value.Tuple [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := + M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| + interpreter + |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| + Value.Tuple [] + |) + |) + |) + |))) + ] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ created_address := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "alloy_primitives::bits::address::Address", + "create2", + [ + Ty.apply + (Ty.path "array") + [ Ty.path "u8" ]; + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "caller" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "to_be_bytes", + [] + |), + [ salt ] + |); + M.read (| tx_initcode_hash |) + ] + |) + |) in + let~ gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::Interpreter", + "gas", + [] + |), + [ M.read (| interpreter |) ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_limit |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |); + M.read (| created_address |); + M.read (| value |); + M.read (| eof |); + M.read (| gas_limit |); + M.read (| return_range |) + ] + |) + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_txcreate : + M.IsFunction "revm_interpreter::instructions::contract::txcreate" txcreate. + + (* + pub fn return_contract(interpreter: &mut Interpreter, _host: &mut H) { + require_init_eof!(interpreter); + let deploy_container_index = unsafe { read_u16(interpreter.instruction_pointer) }; + pop!(interpreter, aux_data_offset, aux_data_size); + let aux_data_size = as_usize_or_fail!(interpreter, aux_data_size); + // important: offset must be ignored if len is zeros + let container = interpreter + .eof() + .expect("EOF is set") + .body + .container_section + .get(deploy_container_index as usize) + .expect("EOF is checked"); + + // convert to EOF so we can check data section size. + let new_eof = Eof::decode(container.clone()).expect("Container is verified"); + + let aux_slice = if aux_data_size != 0 { + let aux_data_offset = as_usize_or_fail!(interpreter, aux_data_offset); + resize_memory!(interpreter, aux_data_offset, aux_data_size); + + interpreter + .shared_memory + .slice(aux_data_offset, aux_data_size) + } else { + &[] + }; + + let new_data_size = new_eof.body.data_section.len() + aux_slice.len(); + if new_data_size > 0xFFFF { + // aux data is too big + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + } + if new_data_size < new_eof.header.data_size as usize { + // aux data is too small + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + } + + // append data bytes + let output = [new_eof.raw(), aux_slice].concat().into(); + + let result = InstructionResult::ReturnContract; + interpreter.instruction_result = result; + interpreter.next_action = crate::InterpreterAction::Return { + result: InterpreterResult { + output, + gas: interpreter.gas, + result, + }, + }; + } + *) + Definition return_contract (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof_init" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::ReturnContractInNotInitEOF" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ deploy_container_index := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::instructions::utility::read_u16", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let aux_data_offset := M.copy (| ฮณ0_0 |) in + let aux_data_size := M.copy (| ฮณ0_1 |) in + let~ aux_data_size := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ aux_data_size ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ container := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "get", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::bytecode::eof::Eof" + ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::Interpreter", + "eof", + [] + |), + [ M.read (| interpreter |) ] + |); + M.read (| Value.String "EOF is set" |) + ] + |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |) + ] + |); + M.rust_cast (M.read (| deploy_container_index |)) + ] + |); + M.read (| Value.String "EOF is checked" |) + ] + |) + |) in + let~ new_eof := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::eof::Eof"; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "decode", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ M.read (| container |) ] + |) + ] + |); + M.read (| Value.String "Container is verified" |) + ] + |) + |) in + let~ aux_slice := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| aux_data_size |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ aux_data_offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ aux_data_offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| aux_data_offset |); M.read (| aux_data_size |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| aux_data_offset |); + M.read (| aux_data_size |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + (* Unsize *) M.pointer_coercion (M.alloc (| Value.Array [] |)) + |))) + ] + |) + |) in + let~ new_data_size := + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + new_eof, + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |) + ] + |) + ] + |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| aux_slice |) ] + |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_data_size |)) + (Value.Integer 65535) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::FatalExternalError" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.read (| new_data_size |)) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + new_eof, + "revm_primitives::bytecode::eof::Eof", + "header" + |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::FatalExternalError" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ output := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ], + "concat", + [ Ty.path "u8" ] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::bytecode::eof::Eof", + "raw", + [] + |), + [ new_eof ] + |) + ] + |) + ] + |); + M.read (| aux_slice |) + ] + |)) + ] + |) + ] + |) + |) in + let~ result := + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| result |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Return" + [ + ("result", + Value.StructRecord + "revm_interpreter::interpreter::InterpreterResult" + [ + ("output", M.read (| output |)); + ("gas", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + |)); + ("result", M.read (| result |)) + ]) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_return_contract : + M.IsFunction "revm_interpreter::instructions::contract::return_contract" return_contract. + + (* + pub fn extcall_input(interpreter: &mut Interpreter) -> Option { + pop_ret!(interpreter, input_offset, input_size, None); + + let return_memory_offset = + resize_memory_and_return_range(interpreter, input_offset, input_size)?; + + Some(Bytes::copy_from_slice( + interpreter + .shared_memory + .slice_range(return_memory_offset.clone()), + )) + } + *) + Definition extcall_input (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ interpreter ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.StructTuple "core::option::Option::None" [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let input_offset := M.copy (| ฮณ0_0 |) in + let input_size := M.copy (| ฮณ0_1 |) in + let~ return_memory_offset := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::resize_memory_and_return_range", + [] + |), + [ + M.read (| interpreter |); + M.read (| input_offset |); + M.read (| input_size |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "core::convert::Infallible" ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice_range", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ return_memory_offset ] + |) + ] + |) + ] + |) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_extcall_input : + M.IsFunction "revm_interpreter::instructions::contract::extcall_input" extcall_input. + + (* + pub fn extcall_gas_calc( + interpreter: &mut Interpreter, + host: &mut H, + target: Address, + transfers_value: bool, + ) -> Option { + let Some(load_result) = host.load_account(target) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return None; + }; + + if load_result.is_cold { + gas!(interpreter, gas::COLD_ACCOUNT_ACCESS_COST, None); + } + + // TODO(EOF) is_empty should only be checked on delegatecall + let call_cost = gas::call_cost( + BerlinSpec::SPEC_ID, + transfers_value, + load_result.is_cold, + load_result.is_empty, + ); + gas!(interpreter, call_cost, None); + + // 7. Calculate the gas available to callee as callerโ€™s + // remaining gas reduced by max(ceil(gas/64), MIN_RETAINED_GAS) (MIN_RETAINED_GAS is 5000). + let gas_reduce = max(interpreter.gas.remaining() / 64, 5000); + let gas_limit = interpreter.gas().remaining().saturating_sub(gas_reduce); + + if gas_limit < 2300 { + interpreter.instruction_result = InstructionResult::CallNotAllowedInsideStatic; + // TODO(EOF) error; + // interpreter.instruction_result = InstructionResult::CallGasTooLow; + return None; + } + + // TODO check remaining gas more then N + + gas!(interpreter, gas_limit, None); + Some(gas_limit) + } + *) + Definition extcall_gas_calc (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host; target; transfers_value ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + let target := M.alloc (| target |) in + let transfers_value := M.alloc (| transfers_value |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "load_account", + [] + |), + [ M.read (| host |); M.read (| target |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let load_result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + load_result, + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::COLD_ACCOUNT_ACCESS_COST" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| + Value.StructTuple + "core::option::Option::None" + [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ call_cost := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::call_cost", [] |), + [ + M.read (| + M.get_constant (| + "revm_primitives::specification::Spec::SPEC_ID" + |) + |); + M.read (| transfers_value |); + M.read (| + M.SubPointer.get_struct_record_field (| + load_result, + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + load_result, + "revm_interpreter::host::LoadAccountResult", + "is_empty" + |) + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| call_cost |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ gas_reduce := + M.alloc (| + M.call_closure (| + M.get_function (| "core::cmp::max", [ Ty.path "u64" ] |), + [ + BinOp.Wrap.div + Integer.U64 + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + ] + |)) + (Value.Integer 64); + Value.Integer 5000 + ] + |) + |) in + let~ gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "saturating_sub", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "gas", + [] + |), + [ M.read (| interpreter |) ] + |) + ] + |); + M.read (| gas_reduce |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt (M.read (| gas_limit |)) (Value.Integer 2300) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallNotAllowedInsideStatic" + [] + |) in + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_limit |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| gas_limit |) ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_extcall_gas_calc : + M.IsFunction "revm_interpreter::instructions::contract::extcall_gas_calc" extcall_gas_calc. + + (* + pub fn extcall(interpreter: &mut Interpreter, host: &mut H) { + require_eof!(interpreter); + pop_address!(interpreter, target_address); + + // input call + let Some(input) = extcall_input(interpreter) else { + return; + }; + + pop!(interpreter, value); + let has_transfer = value != U256::ZERO; + + let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, has_transfer) else { + return; + }; + // TODO Check if static and value 0 + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address, + caller: interpreter.contract.target_address, + bytecode_address: target_address, + value: CallValue::Transfer(value), + scheme: CallScheme::Call, + is_static: interpreter.is_static, + is_eof: true, + return_memory_offset: 0..0, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; + } + *) + Definition extcall (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ target_address := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::extcall_input", + [] + |), + [ M.read (| interpreter |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let input := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ value := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ has_transfer := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ value; M.get_constant (| "ruint::ZERO" |) ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::extcall_gas_calc", + [ H ] + |), + [ + M.read (| interpreter |); + M.read (| host |); + M.read (| target_address |); + M.read (| has_transfer |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_limit := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Call" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter_action::call_inputs::CallInputs" + [ + ("input", M.read (| input |)); + ("gas_limit", M.read (| gas_limit |)); + ("target_address", M.read (| target_address |)); + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("bytecode_address", M.read (| target_address |)); + ("value", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer" + [ M.read (| value |) ]); + ("scheme", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallScheme::Call" + []); + ("is_static", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |) + |)); + ("is_eof", Value.Bool true); + ("return_memory_offset", + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", Value.Integer 0) + ]) + ] + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_extcall : + M.IsFunction "revm_interpreter::instructions::contract::extcall" extcall. + + (* + pub fn extdcall(interpreter: &mut Interpreter, host: &mut H) { + require_eof!(interpreter); + pop_address!(interpreter, target_address); + + // input call + let Some(input) = extcall_input(interpreter) else { + return; + }; + + let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, false) else { + return; + }; + // TODO Check if static and value 0 + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address, + caller: interpreter.contract.target_address, + bytecode_address: target_address, + value: CallValue::Apparent(interpreter.contract.call_value), + // TODO(EOF) should be EofDelegateCall? + scheme: CallScheme::DelegateCall, + is_static: interpreter.is_static, + is_eof: true, + return_memory_offset: 0..0, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; + } + *) + Definition extdcall (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ target_address := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::extcall_input", + [] + |), + [ M.read (| interpreter |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let input := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::extcall_gas_calc", + [ H ] + |), + [ + M.read (| interpreter |); + M.read (| host |); + M.read (| target_address |); + Value.Bool false + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_limit := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Call" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter_action::call_inputs::CallInputs" + [ + ("input", M.read (| input |)); + ("gas_limit", M.read (| gas_limit |)); + ("target_address", M.read (| target_address |)); + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("bytecode_address", M.read (| target_address |)); + ("value", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "call_value" + |) + |) + ]); + ("scheme", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallScheme::DelegateCall" + []); + ("is_static", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |) + |)); + ("is_eof", Value.Bool true); + ("return_memory_offset", + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", Value.Integer 0) + ]) + ] + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_extdcall : + M.IsFunction "revm_interpreter::instructions::contract::extdcall" extdcall. + + (* + pub fn extscall(interpreter: &mut Interpreter, host: &mut H) { + require_eof!(interpreter); + pop_address!(interpreter, target_address); + + // input call + let Some(input) = extcall_input(interpreter) else { + return; + }; + + let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, false) else { + return; + }; + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address, + caller: interpreter.contract.target_address, + bytecode_address: target_address, + value: CallValue::Transfer(U256::ZERO), + scheme: CallScheme::Call, + is_static: interpreter.is_static, + is_eof: true, + return_memory_offset: 0..0, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; + } + *) + Definition extscall (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ target_address := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::extcall_input", + [] + |), + [ M.read (| interpreter |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let input := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::extcall_gas_calc", + [ H ] + |), + [ + M.read (| interpreter |); + M.read (| host |); + M.read (| target_address |); + Value.Bool false + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_limit := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Call" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter_action::call_inputs::CallInputs" + [ + ("input", M.read (| input |)); + ("gas_limit", M.read (| gas_limit |)); + ("target_address", M.read (| target_address |)); + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("bytecode_address", M.read (| target_address |)); + ("value", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer" + [ + M.read (| + M.get_constant (| "ruint::ZERO" |) + |) + ]); + ("scheme", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallScheme::Call" + []); + ("is_static", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |) + |)); + ("is_eof", Value.Bool true); + ("return_memory_offset", + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", Value.Integer 0) + ]) + ] + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_extscall : + M.IsFunction "revm_interpreter::instructions::contract::extscall" extscall. + + (* + pub fn create( + interpreter: &mut Interpreter, + host: &mut H, + ) { + require_non_staticcall!(interpreter); + + // EIP-1014: Skinny CREATE2 + if IS_CREATE2 { + check!(interpreter, PETERSBURG); + } + + pop!(interpreter, value, code_offset, len); + let len = as_usize_or_fail!(interpreter, len); + + let mut code = Bytes::new(); + if len != 0 { + // EIP-3860: Limit and meter initcode + if SPEC::enabled(SHANGHAI) { + // Limit is set as double of max contract bytecode size + let max_initcode_size = host + .env() + .cfg + .limit_contract_code_size + .map(|limit| limit.saturating_mul(2)) + .unwrap_or(MAX_INITCODE_SIZE); + if len > max_initcode_size { + interpreter.instruction_result = InstructionResult::CreateInitCodeSizeLimit; + return; + } + gas!(interpreter, gas::initcode_cost(len as u64)); + } + + let code_offset = as_usize_or_fail!(interpreter, code_offset); + resize_memory!(interpreter, code_offset, len); + code = Bytes::copy_from_slice(interpreter.shared_memory.slice(code_offset, len)); + } + + // EIP-1014: Skinny CREATE2 + let scheme = if IS_CREATE2 { + pop!(interpreter, salt); + // SAFETY: len is reasonable in size as gas for it is already deducted. + gas_or_fail!(interpreter, gas::create2_cost(len.try_into().unwrap())); + CreateScheme::Create2 { salt } + } else { + gas!(interpreter, gas::CREATE); + CreateScheme::Create + }; + + let mut gas_limit = interpreter.gas().remaining(); + + // EIP-150: Gas cost changes for IO-heavy operations + if SPEC::enabled(TANGERINE) { + // take remaining gas and deduce l64 part of it. + gas_limit -= gas_limit / 64 + } + gas!(interpreter, gas_limit); + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Create { + inputs: Box::new(CreateInputs { + caller: interpreter.contract.target_address, + scheme, + value, + init_code: code, + gas_limit, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; + } + *) + Definition create (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.get_constant (| + "revm_interpreter::instructions::contract::create::IS_CREATE2" + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::PETERSBURG" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 3) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop3_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let value := M.copy (| ฮณ0_0 |) in + let code_offset := M.copy (| ฮณ0_1 |) in + let len := M.copy (| ฮณ0_2 |) in + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ len ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ code := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::SHANGHAI" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ max_initcode_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "usize" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "usize" ], + "map", + [ + Ty.path "usize"; + Ty.function + [ Ty.tuple [ Ty.path "usize" ] ] + (Ty.path "usize") + ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "cfg" + |), + "revm_primitives::env::CfgEnv", + "limit_contract_code_size" + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let limit := + M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_mul", + [] + |), + [ + M.read (| limit |); + Value.Integer 2 + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + M.read (| + M.get_constant (| + "revm_primitives::constants::MAX_INITCODE_SIZE" + |) + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| len |)) + (M.read (| max_initcode_size |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CreateInitCodeSizeLimit" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::initcode_cost", + [] + |), + [ M.rust_cast (M.read (| len |)) + ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ code_offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ code_offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| code_offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + code, + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| code_offset |); + M.read (| len |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ scheme := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.get_constant (| + "revm_interpreter::instructions::contract::create::IS_CREATE2" + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ salt := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::create2_cost", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.path "core::num::error::TryFromIntError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.path "usize", + [ Ty.path "u64" ], + "try_into", + [] + |), + [ M.read (| len |) ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| + Value.StructRecord + "revm_primitives::env::CreateScheme::Create2" + [ ("salt", M.read (| salt |)) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::CREATE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::env::CreateScheme::Create" + [] + |))) + ] + |) + |) in + let~ gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "gas", + [] + |), + [ M.read (| interpreter |) ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::TANGERINE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let ฮฒ := gas_limit in + M.write (| + ฮฒ, + BinOp.Wrap.sub + Integer.U64 + (M.read (| ฮฒ |)) + (BinOp.Wrap.div + Integer.U64 + (M.read (| gas_limit |)) + (Value.Integer 64)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_limit |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Create" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter_action::create_inputs::CreateInputs" + [ + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("scheme", M.read (| scheme |)); + ("value", M.read (| value |)); + ("init_code", M.read (| code |)); + ("gas_limit", M.read (| gas_limit |)) + ] + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_create : M.IsFunction "revm_interpreter::instructions::contract::create" create. + + (* + pub fn call(interpreter: &mut Interpreter, host: &mut H) { + pop!(interpreter, local_gas_limit); + pop_address!(interpreter, to); + // max gas limit is not possible in real ethereum situation. + let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); + + pop!(interpreter, value); + let has_transfer = value != U256::ZERO; + if interpreter.is_static && has_transfer { + interpreter.instruction_result = InstructionResult::CallNotAllowedInsideStatic; + return; + } + + let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else { + return; + }; + + let Some(LoadAccountResult { is_cold, is_empty }) = host.load_account(to) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + let Some(mut gas_limit) = calc_call_gas::( + interpreter, + is_cold, + has_transfer, + is_empty, + local_gas_limit, + ) else { + return; + }; + + gas!(interpreter, gas_limit); + + // add call stipend if there is value to be transferred. + if has_transfer { + gas_limit = gas_limit.saturating_add(gas::CALL_STIPEND); + } + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address: to, + caller: interpreter.contract.target_address, + bytecode_address: to, + value: CallValue::Transfer(value), + scheme: CallScheme::Call, + is_static: interpreter.is_static, + is_eof: false, + return_memory_offset, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; + } + *) + Definition call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ local_gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ to := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + let~ local_gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply (Ty.path "ruint::from::FromUintError") [ Ty.path "u64" ] + ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "u64", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ M.read (| local_gas_limit |) ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ value := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ has_transfer := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ value; M.get_constant (| "ruint::ZERO" |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |) + |), + ltac:(M.monadic (M.read (| has_transfer |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallNotAllowedInsideStatic" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::get_memory_input_and_out_ranges", + [] + |), + [ M.read (| interpreter |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let input := M.copy (| ฮณ1_0 |) in + let return_memory_offset := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "load_account", + [] + |), + [ M.read (| host |); M.read (| to |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::host::LoadAccountResult", + "is_empty" + |) in + let is_cold := M.copy (| ฮณ1_0 |) in + let is_empty := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::calc_call_gas", + [ H; SPEC ] + |), + [ + M.read (| interpreter |); + M.read (| is_cold |); + M.read (| has_transfer |); + M.read (| is_empty |); + M.read (| local_gas_limit |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_limit := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_limit |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use has_transfer in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + gas_limit, + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "saturating_add", + [] + |), + [ + M.read (| gas_limit |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::CALL_STIPEND" + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Call" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter_action::call_inputs::CallInputs" + [ + ("input", M.read (| input |)); + ("gas_limit", M.read (| gas_limit |)); + ("target_address", M.read (| to |)); + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("bytecode_address", M.read (| to |)); + ("value", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer" + [ M.read (| value |) ]); + ("scheme", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallScheme::Call" + []); + ("is_static", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |) + |)); + ("is_eof", Value.Bool false); + ("return_memory_offset", + M.read (| return_memory_offset |)) + ] + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_call : M.IsFunction "revm_interpreter::instructions::contract::call" call. + + (* + pub fn call_code(interpreter: &mut Interpreter, host: &mut H) { + pop!(interpreter, local_gas_limit); + pop_address!(interpreter, to); + // max gas limit is not possible in real ethereum situation. + let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); + + pop!(interpreter, value); + let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else { + return; + }; + + let Some(LoadAccountResult { is_cold, .. }) = host.load_account(to) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + + let Some(mut gas_limit) = calc_call_gas::( + interpreter, + is_cold, + value != U256::ZERO, + false, + local_gas_limit, + ) else { + return; + }; + + gas!(interpreter, gas_limit); + + // add call stipend if there is value to be transferred. + if value != U256::ZERO { + gas_limit = gas_limit.saturating_add(gas::CALL_STIPEND); + } + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address: interpreter.contract.target_address, + caller: interpreter.contract.target_address, + bytecode_address: to, + value: CallValue::Transfer(value), + scheme: CallScheme::CallCode, + is_static: interpreter.is_static, + is_eof: false, + return_memory_offset, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; + } + *) + Definition call_code (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ local_gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ to := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + let~ local_gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply (Ty.path "ruint::from::FromUintError") [ Ty.path "u64" ] + ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "u64", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ M.read (| local_gas_limit |) ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ value := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::get_memory_input_and_out_ranges", + [] + |), + [ M.read (| interpreter |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let input := M.copy (| ฮณ1_0 |) in + let return_memory_offset := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "load_account", + [] + |), + [ M.read (| host |); M.read (| to |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |) in + let is_cold := M.copy (| ฮณ1_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::calc_call_gas", + [ H; SPEC ] + |), + [ + M.read (| interpreter |); + M.read (| is_cold |); + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ value; M.get_constant (| "ruint::ZERO" |) ] + |); + Value.Bool false; + M.read (| local_gas_limit |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_limit := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_limit |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ + value; + M.get_constant (| "ruint::ZERO" |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + gas_limit, + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "saturating_add", + [] + |), + [ + M.read (| gas_limit |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::CALL_STIPEND" + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Call" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter_action::call_inputs::CallInputs" + [ + ("input", M.read (| input |)); + ("gas_limit", M.read (| gas_limit |)); + ("target_address", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("bytecode_address", M.read (| to |)); + ("value", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer" + [ M.read (| value |) ]); + ("scheme", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallScheme::CallCode" + []); + ("is_static", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |) + |)); + ("is_eof", Value.Bool false); + ("return_memory_offset", + M.read (| return_memory_offset |)) + ] + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_call_code : + M.IsFunction "revm_interpreter::instructions::contract::call_code" call_code. + + (* + pub fn delegate_call(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, HOMESTEAD); + pop!(interpreter, local_gas_limit); + pop_address!(interpreter, to); + // max gas limit is not possible in real ethereum situation. + let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); + + let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else { + return; + }; + + let Some(LoadAccountResult { is_cold, .. }) = host.load_account(to) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + let Some(gas_limit) = + calc_call_gas::(interpreter, is_cold, false, false, local_gas_limit) + else { + return; + }; + + gas!(interpreter, gas_limit); + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address: interpreter.contract.target_address, + caller: interpreter.contract.caller, + bytecode_address: to, + value: CallValue::Apparent(interpreter.contract.call_value), + scheme: CallScheme::DelegateCall, + is_static: interpreter.is_static, + is_eof: false, + return_memory_offset, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; + } + *) + Definition delegate_call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::HOMESTEAD" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ local_gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ to := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + let~ local_gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply (Ty.path "ruint::from::FromUintError") [ Ty.path "u64" ] + ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "u64", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ M.read (| local_gas_limit |) ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::get_memory_input_and_out_ranges", + [] + |), + [ M.read (| interpreter |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let input := M.copy (| ฮณ1_0 |) in + let return_memory_offset := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "load_account", + [] + |), + [ M.read (| host |); M.read (| to |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |) in + let is_cold := M.copy (| ฮณ1_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::calc_call_gas", + [ H; SPEC ] + |), + [ + M.read (| interpreter |); + M.read (| is_cold |); + Value.Bool false; + Value.Bool false; + M.read (| local_gas_limit |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_limit := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_limit |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Call" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter_action::call_inputs::CallInputs" + [ + ("input", M.read (| input |)); + ("gas_limit", M.read (| gas_limit |)); + ("target_address", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "caller" + |) + |)); + ("bytecode_address", M.read (| to |)); + ("value", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "call_value" + |) + |) + ]); + ("scheme", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallScheme::DelegateCall" + []); + ("is_static", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |) + |)); + ("is_eof", Value.Bool false); + ("return_memory_offset", + M.read (| return_memory_offset |)) + ] + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_delegate_call : + M.IsFunction "revm_interpreter::instructions::contract::delegate_call" delegate_call. + + (* + pub fn static_call(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, BYZANTIUM); + pop!(interpreter, local_gas_limit); + pop_address!(interpreter, to); + // max gas limit is not possible in real ethereum situation. + let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); + + let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else { + return; + }; + + let Some(LoadAccountResult { is_cold, .. }) = host.load_account(to) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + + let Some(gas_limit) = + calc_call_gas::(interpreter, is_cold, false, false, local_gas_limit) + else { + return; + }; + gas!(interpreter, gas_limit); + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address: to, + caller: interpreter.contract.target_address, + bytecode_address: to, + value: CallValue::Transfer(U256::ZERO), + scheme: CallScheme::StaticCall, + is_static: true, + is_eof: false, + return_memory_offset, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; + } + *) + Definition static_call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::BYZANTIUM" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ local_gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ to := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + let~ local_gas_limit := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply (Ty.path "ruint::from::FromUintError") [ Ty.path "u64" ] + ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "u64", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ M.read (| local_gas_limit |) ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::get_memory_input_and_out_ranges", + [] + |), + [ M.read (| interpreter |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let input := M.copy (| ฮณ1_0 |) in + let return_memory_offset := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "load_account", + [] + |), + [ M.read (| host |); M.read (| to |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |) in + let is_cold := M.copy (| ฮณ1_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::calc_call_gas", + [ H; SPEC ] + |), + [ + M.read (| interpreter |); + M.read (| is_cold |); + Value.Bool false; + Value.Bool false; + M.read (| local_gas_limit |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_limit := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_limit |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Call" + [ + ("inputs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter_action::call_inputs::CallInputs" + [ + ("input", M.read (| input |)); + ("gas_limit", M.read (| gas_limit |)); + ("target_address", M.read (| to |)); + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("bytecode_address", M.read (| to |)); + ("value", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer" + [ + M.read (| + M.get_constant (| "ruint::ZERO" |) + |) + ]); + ("scheme", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallScheme::StaticCall" + []); + ("is_static", Value.Bool true); + ("is_eof", Value.Bool false); + ("return_memory_offset", + M.read (| return_memory_offset |)) + ] + ] + |)) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallOrCreate" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_static_call : + M.IsFunction "revm_interpreter::instructions::contract::static_call" static_call. + End contract. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/contract/call_helpers.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/contract/call_helpers.md new file mode 100644 index 00000000..79e111cc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/contract/call_helpers.md @@ -0,0 +1,966 @@ +# ๐Ÿ“ call_helpers.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/contract/call_helpers.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module contract. + Module call_helpers. + (* + pub fn get_memory_input_and_out_ranges( + interpreter: &mut Interpreter, + ) -> Option<(Bytes, Range)> { + pop_ret!(interpreter, in_offset, in_len, out_offset, out_len, None); + + let in_range = resize_memory_and_return_range(interpreter, in_offset, in_len)?; + + let mut input = Bytes::new(); + if !in_range.is_empty() { + input = Bytes::copy_from_slice(interpreter.shared_memory.slice_range(in_range)); + } + + let ret_range = resize_memory_and_return_range(interpreter, out_offset, out_len)?; + Some((input, ret_range)) + } + *) + Definition get_memory_input_and_out_ranges (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ interpreter ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 4) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.StructTuple "core::option::Option::None" [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop4_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let ฮณ0_3 := M.SubPointer.get_tuple_field (| ฮณ, 3 |) in + let in_offset := M.copy (| ฮณ0_0 |) in + let in_len := M.copy (| ฮณ0_1 |) in + let out_offset := M.copy (| ฮณ0_2 |) in + let out_len := M.copy (| ฮณ0_3 |) in + let~ in_range := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::resize_memory_and_return_range", + [] + |), + [ + M.read (| interpreter |); + M.read (| in_offset |); + M.read (| in_len |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ] + ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "core::convert::Infallible" ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ input := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + "is_empty", + [] + |), + [ in_range ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + input, + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice_range", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| in_range |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ ret_range := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::contract::call_helpers::resize_memory_and_return_range", + [] + |), + [ + M.read (| interpreter |); + M.read (| out_offset |); + M.read (| out_len |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ] + ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "core::convert::Infallible" ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.Tuple [ M.read (| input |); M.read (| ret_range |) ] ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_get_memory_input_and_out_ranges : + M.IsFunction + "revm_interpreter::instructions::contract::call_helpers::get_memory_input_and_out_ranges" + get_memory_input_and_out_ranges. + + (* + pub fn resize_memory_and_return_range( + interpreter: &mut Interpreter, + offset: U256, + len: U256, + ) -> Option> { + let len = as_usize_or_fail_ret!(interpreter, len, None); + let offset = if len != 0 { + let offset = as_usize_or_fail_ret!(interpreter, offset, None); + resize_memory!(interpreter, offset, len, None); + offset + } else { + usize::MAX //unrealistic value so we are sure it is not used + }; + Some(offset..offset + len) + } + *) + Definition resize_memory_and_return_range (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ interpreter; offset; len ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let offset := M.alloc (| offset |) in + let len := M.alloc (| len |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "as_limbs", [] |), + [ len ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ offset := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| + Value.StructTuple + "core::option::Option::None" + [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| + Value.StructTuple + "core::option::Option::None" + [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + offset)); + fun ฮณ => ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| offset |)); + ("end_", + BinOp.Wrap.add Integer.Usize (M.read (| offset |)) (M.read (| len |))) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_resize_memory_and_return_range : + M.IsFunction + "revm_interpreter::instructions::contract::call_helpers::resize_memory_and_return_range" + resize_memory_and_return_range. + + (* + pub fn calc_call_gas( + interpreter: &mut Interpreter, + is_cold: bool, + has_transfer: bool, + new_account_accounting: bool, + local_gas_limit: u64, + ) -> Option { + let call_cost = gas::call_cost(SPEC::SPEC_ID, has_transfer, is_cold, new_account_accounting); + + gas!(interpreter, call_cost, None); + + // EIP-150: Gas cost changes for IO-heavy operations + let gas_limit = if SPEC::enabled(TANGERINE) { + let gas = interpreter.gas().remaining(); + // take l64 part of gas_limit + min(gas - gas / 64, local_gas_limit) + } else { + local_gas_limit + }; + + Some(gas_limit) + } + *) + Definition calc_call_gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], + [ interpreter; is_cold; has_transfer; new_account_accounting; local_gas_limit ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let is_cold := M.alloc (| is_cold |) in + let has_transfer := M.alloc (| has_transfer |) in + let new_account_accounting := M.alloc (| new_account_accounting |) in + let local_gas_limit := M.alloc (| local_gas_limit |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ call_cost := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::call_cost", [] |), + [ + M.read (| + M.get_constant (| "revm_primitives::specification::Spec::SPEC_ID" |) + |); + M.read (| has_transfer |); + M.read (| is_cold |); + M.read (| new_account_accounting |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| call_cost |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.StructTuple "core::option::Option::None" [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ gas_limit := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::TANGERINE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ gas := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "gas", + [] + |), + [ M.read (| interpreter |) ] + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_function (| "core::cmp::min", [ Ty.path "u64" ] |), + [ + BinOp.Wrap.sub + Integer.U64 + (M.read (| gas |)) + (BinOp.Wrap.div + Integer.U64 + (M.read (| gas |)) + (Value.Integer 64)); + M.read (| local_gas_limit |) + ] + |) + |))); + fun ฮณ => ltac:(M.monadic local_gas_limit) + ] + |) + |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| gas_limit |) ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_calc_call_gas : + M.IsFunction + "revm_interpreter::instructions::contract::call_helpers::calc_call_gas" + calc_call_gas. + End call_helpers. + End contract. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/control.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/control.md new file mode 100644 index 00000000..c2e4f9ee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/control.md @@ -0,0 +1,2999 @@ +# ๐Ÿ“ control.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/control.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module control. + (* + pub fn rjump(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::BASE); + let offset = unsafe { read_i16(interpreter.instruction_pointer) } as isize; + // In spec it is +3 but pointer is already incremented in + // `Interpreter::step` so for revm is +2. + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(offset + 2) }; + } + *) + Definition rjump (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ offset := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_i16", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + ] + |)) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + BinOp.Wrap.add Integer.Isize (M.read (| offset |)) (Value.Integer 2) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_rjump : M.IsFunction "revm_interpreter::instructions::control::rjump" rjump. + + (* + pub fn rjumpi(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::CONDITION_JUMP_GAS); + pop!(interpreter, condition); + // In spec it is +3 but pointer is already incremented in + // `Interpreter::step` so for revm is +2. + let mut offset = 2; + if !condition.is_zero() { + offset += unsafe { read_i16(interpreter.instruction_pointer) } as isize; + } + + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(offset) }; + } + *) + Definition rjumpi (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::CONDITION_JUMP_GAS" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ condition := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ offset := M.alloc (| Value.Integer 2 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "is_zero", + [] + |), + [ condition ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + let ฮฒ := offset in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Isize + (M.read (| ฮฒ |)) + (M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_i16", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + ] + |))) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + M.read (| offset |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_rjumpi : M.IsFunction "revm_interpreter::instructions::control::rjumpi" rjumpi. + + (* + pub fn rjumpv(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::CONDITION_JUMP_GAS); + pop!(interpreter, case); + let case = as_isize_saturated!(case); + + let max_index = unsafe { *interpreter.instruction_pointer } as isize; + // for number of items we are adding 1 to max_index, multiply by 2 as each offset is 2 bytes + // and add 1 for max_index itself. Note that revm already incremented the instruction pointer + let mut offset = (max_index + 1) * 2 + 1; + + if case <= max_index { + offset += unsafe { + read_i16( + interpreter + .instruction_pointer + // offset for max_index that is one byte + .offset(1 + case * 2), + ) + } as isize; + } + + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(offset) }; + } + *) + Definition rjumpv (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::CONDITION_JUMP_GAS" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ case := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ case := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "isize"; Ty.path "core::num::error::TryFromIntError" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "isize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ case ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ max_index := + M.alloc (| + M.rust_cast + (M.read (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + |)) + |) in + let~ offset := + M.alloc (| + BinOp.Wrap.add + Integer.Isize + (BinOp.Wrap.mul + Integer.Isize + (BinOp.Wrap.add Integer.Isize (M.read (| max_index |)) (Value.Integer 1)) + (Value.Integer 2)) + (Value.Integer 1) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.le (M.read (| case |)) (M.read (| max_index |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + let ฮฒ := offset in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Isize + (M.read (| ฮฒ |)) + (M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_i16", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + BinOp.Wrap.add + Integer.Isize + (Value.Integer 1) + (BinOp.Wrap.mul + Integer.Isize + (M.read (| case |)) + (Value.Integer 2)) + ] + |) + ] + |))) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + M.read (| offset |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_rjumpv : M.IsFunction "revm_interpreter::instructions::control::rjumpv" rjumpv. + + (* + pub fn jump(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::MID); + pop!(interpreter, target); + jump_inner(interpreter, target); + } + *) + Definition jump (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::MID" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ target := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::control::jump_inner", + [] + |), + [ M.read (| interpreter |); M.read (| target |) ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_jump : M.IsFunction "revm_interpreter::instructions::control::jump" jump. + + (* + pub fn jumpi(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::HIGH); + pop!(interpreter, target, cond); + if cond != U256::ZERO { + jump_inner(interpreter, target); + } + } + *) + Definition jumpi (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::HIGH" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let target := M.copy (| ฮณ0_0 |) in + let cond := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ cond; M.get_constant (| "ruint::ZERO" |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::control::jump_inner", + [] + |), + [ M.read (| interpreter |); M.read (| target |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_jumpi : M.IsFunction "revm_interpreter::instructions::control::jumpi" jumpi. + + (* + fn jump_inner(interpreter: &mut Interpreter, target: U256) { + let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump); + if !interpreter.contract.is_valid_jump(target) { + interpreter.instruction_result = InstructionResult::InvalidJump; + return; + } + // SAFETY: `is_valid_jump` ensures that `dest` is in bounds. + interpreter.instruction_pointer = unsafe { interpreter.bytecode.as_ptr().add(target) }; + } + *) + Definition jump_inner (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ interpreter; target ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let target := M.alloc (| target |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ target := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "as_limbs", [] |), + [ target ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidJump" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::contract::Contract", + "is_valid_jump", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |); + M.read (| target |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidJump" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "bytecode" + |) + ] + |) + ] + |) + ] + |); + M.read (| target |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_jump_inner : + M.IsFunction "revm_interpreter::instructions::control::jump_inner" jump_inner. + + (* + pub fn jumpdest_or_nop(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::JUMPDEST); + } + *) + Definition jumpdest_or_nop (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::JUMPDEST" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_jumpdest_or_nop : + M.IsFunction "revm_interpreter::instructions::control::jumpdest_or_nop" jumpdest_or_nop. + + (* + pub fn callf(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::LOW); + + let idx = unsafe { read_u16(interpreter.instruction_pointer) } as usize; + // TODO Check stack with EOF types. + + if interpreter.function_stack.return_stack_len() == 1024 { + interpreter.instruction_result = InstructionResult::EOFFunctionStackOverflow; + return; + } + + // push current idx and PC to the callf stack. + // PC is incremented by 2 to point to the next instruction after callf. + interpreter + .function_stack + .push(interpreter.program_counter() + 2, idx); + + interpreter.load_eof_code(idx, 0) + } + *) + Definition callf (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOW" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ idx := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_u16", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + ] + |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::function_stack::FunctionStack", + "return_stack_len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "function_stack" + |) + ] + |)) + (Value.Integer 1024) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFFunctionStackOverflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::function_stack::FunctionStack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "function_stack" + |); + BinOp.Wrap.add + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "program_counter", + [] + |), + [ M.read (| interpreter |) ] + |)) + (Value.Integer 2); + M.read (| idx |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "load_eof_code", + [] + |), + [ M.read (| interpreter |); M.read (| idx |); Value.Integer 0 ] + |) + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_callf : M.IsFunction "revm_interpreter::instructions::control::callf" callf. + + (* + pub fn retf(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::RETF_GAS); + + let Some(fframe) = interpreter.function_stack.pop() else { + panic!("Expected function frame") + }; + + interpreter.load_eof_code(fframe.idx, fframe.pc); + } + *) + Definition retf (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::RETF_GAS" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::function_stack::FunctionStack", + "pop", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "function_stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let fframe := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "load_eof_code", + [] + |), + [ + M.read (| interpreter |); + M.read (| + M.SubPointer.get_struct_record_field (| + fframe, + "revm_interpreter::function_stack::FunctionReturnFrame", + "idx" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + fframe, + "revm_interpreter::function_stack::FunctionReturnFrame", + "pc" + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_retf : M.IsFunction "revm_interpreter::instructions::control::retf" retf. + + (* + pub fn jumpf(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::LOW); + + let idx = unsafe { read_u16(interpreter.instruction_pointer) } as usize; + + // TODO(EOF) do types stack checks + + interpreter.function_stack.set_current_code_idx(idx); + interpreter.load_eof_code(idx, 0) + } + *) + Definition jumpf (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOW" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ idx := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_u16", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + ] + |)) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::function_stack::FunctionStack", + "set_current_code_idx", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "function_stack" + |); + M.read (| idx |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "load_eof_code", + [] + |), + [ M.read (| interpreter |); M.read (| idx |); Value.Integer 0 ] + |) + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_jumpf : M.IsFunction "revm_interpreter::instructions::control::jumpf" jumpf. + + (* + pub fn pc(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + // - 1 because we have already advanced the instruction pointer in `Interpreter::step` + push!(interpreter, U256::from(interpreter.program_counter() - 1)); + } + *) + Definition pc (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "usize" ] + |), + [ + BinOp.Wrap.sub + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "program_counter", + [] + |), + [ M.read (| interpreter |) ] + |)) + (Value.Integer 1) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_pc : M.IsFunction "revm_interpreter::instructions::control::pc" pc. + + (* + fn return_inner(interpreter: &mut Interpreter, instruction_result: InstructionResult) { + // zero gas cost + // gas!(interpreter, gas::ZERO); + pop!(interpreter, offset, len); + let len = as_usize_or_fail!(interpreter, len); + // important: offset must be ignored if len is zeros + let mut output = Bytes::default(); + if len != 0 { + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, len); + + output = interpreter.shared_memory.slice(offset, len).to_vec().into() + } + interpreter.instruction_result = instruction_result; + interpreter.next_action = crate::InterpreterAction::Return { + result: InterpreterResult { + output, + gas: interpreter.gas, + result: instruction_result, + }, + }; + } + *) + Definition return_inner (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ interpreter; instruction_result ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let instruction_result := M.alloc (| instruction_result |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let offset := M.copy (| ฮณ0_0 |) in + let len := M.copy (| ฮณ0_1 |) in + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ len ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ output := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "default", + [] + |), + [] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.write (| + output, + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "to_vec", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| offset |); + M.read (| len |) + ] + |) + ] + |) + ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| instruction_result |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Return" + [ + ("result", + Value.StructRecord + "revm_interpreter::interpreter::InterpreterResult" + [ + ("output", M.read (| output |)); + ("gas", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + |)); + ("result", M.read (| instruction_result |)) + ]) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_return_inner : + M.IsFunction "revm_interpreter::instructions::control::return_inner" return_inner. + + (* + pub fn ret(interpreter: &mut Interpreter, _host: &mut H) { + return_inner(interpreter, InstructionResult::Return); + } + *) + Definition ret (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::instructions::control::return_inner", [] |), + [ + M.read (| interpreter |); + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Return" + [] + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_ret : M.IsFunction "revm_interpreter::instructions::control::ret" ret. + + (* + pub fn revert(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, BYZANTIUM); + return_inner(interpreter, InstructionResult::Revert); + } + *) + Definition revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::BYZANTIUM" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::control::return_inner", + [] + |), + [ + M.read (| interpreter |); + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Revert" + [] + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_revert : M.IsFunction "revm_interpreter::instructions::control::revert" revert. + + (* + pub fn stop(interpreter: &mut Interpreter, _host: &mut H) { + interpreter.instruction_result = InstructionResult::Stop; + } + *) + Definition stop (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple "revm_interpreter::instruction_result::InstructionResult::Stop" [] + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_stop : M.IsFunction "revm_interpreter::instructions::control::stop" stop. + + (* + pub fn invalid(interpreter: &mut Interpreter, _host: &mut H) { + interpreter.instruction_result = InstructionResult::InvalidFEOpcode; + } + *) + Definition invalid (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidFEOpcode" + [] + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_invalid : + M.IsFunction "revm_interpreter::instructions::control::invalid" invalid. + + (* + pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { + interpreter.instruction_result = InstructionResult::OpcodeNotFound; + } + *) + Definition unknown (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OpcodeNotFound" + [] + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_unknown : + M.IsFunction "revm_interpreter::instructions::control::unknown" unknown. + End control. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/data.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/data.md new file mode 100644 index 00000000..f60fc65b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/data.md @@ -0,0 +1,1663 @@ +# ๐Ÿ“ data.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/data.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module data. + (* + pub fn data_load(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, DATA_LOAD_GAS); + pop_top!(interpreter, offset); + + let offset_usize = as_usize_saturated!(offset); + + let slice = interpreter + .contract + .bytecode + .eof() + .expect("eof") + .data_slice(offset_usize, 32); + + let mut word = [0u8; 32]; + word[..slice.len()].copy_from_slice(slice); + + *offset = U256::from_be_bytes(word); + } + *) + Definition data_load (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::DATA_LOAD_GAS" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ offset := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ offset_usize := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ M.read (| offset |) ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ slice := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "data_slice", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::bytecode::eof::Eof" ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "eof", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |); + M.read (| Value.String "eof" |) + ] + |); + M.read (| offset_usize |); + Value.Integer 32 + ] + |) + |) in + let~ word := M.alloc (| repeat (Value.Integer 0) 32 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ], + "index_mut", + [] + |), + [ + word; + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| slice |) ] + |)) + ] + ] + |); + M.read (| slice |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| offset |), + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from_be_bytes", [] |), + [ M.read (| word |) ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_data_load : + M.IsFunction "revm_interpreter::instructions::data::data_load" data_load. + + (* + pub fn data_loadn(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, VERYLOW); + let offset = unsafe { read_u16(interpreter.instruction_pointer) } as usize; + + let slice = interpreter + .contract + .bytecode + .eof() + .expect("eof") + .data_slice(offset, 32); + + let mut word = [0u8; 32]; + word[..slice.len()].copy_from_slice(slice); + + push_b256!(interpreter, word.into()); + + // add +2 to the instruction pointer to skip the offset + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(2) }; + } + *) + Definition data_loadn (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ offset := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_u16", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + ] + |)) + |) in + let~ slice := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "data_slice", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::bytecode::eof::Eof" ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "eof", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |); + M.read (| Value.String "eof" |) + ] + |); + M.read (| offset |); + Value.Integer 32 + ] + |) + |) in + let~ word := M.alloc (| repeat (Value.Integer 0) 32 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ], + "index_mut", + [] + |), + [ + word; + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| slice |) ] + |)) + ] + ] + |); + M.read (| slice |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_b256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "into", + [] + |), + [ M.read (| word |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + Value.Integer 2 + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_data_loadn : + M.IsFunction "revm_interpreter::instructions::data::data_loadn" data_loadn. + + (* + pub fn data_size(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, BASE); + let data_size = interpreter.eof().expect("eof").header.data_size; + + push!(interpreter, U256::from(data_size)); + } + *) + Definition data_size (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ data_size := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::bytecode::eof::Eof" ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "eof", + [] + |), + [ M.read (| interpreter |) ] + |); + M.read (| Value.String "eof" |) + ] + |), + "revm_primitives::bytecode::eof::Eof", + "header" + |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u16" ] + |), + [ M.read (| data_size |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_data_size : + M.IsFunction "revm_interpreter::instructions::data::data_size" data_size. + + (* + pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, VERYLOW); + pop!(interpreter, mem_offset, offset, size); + + // sizes more than u64::MAX will spend all the gas in memmory resize. + let size = as_usize_or_fail!(interpreter, size); + // size of zero should not change the memory + if size == 0 { + return; + } + // fail if mem offset is big as it will spend all the gas + let mem_offset = as_usize_or_fail!(interpreter, mem_offset); + resize_memory!(interpreter, mem_offset, size); + + let offset = as_usize_saturated!(offset); + let data = interpreter.contract.bytecode.eof().expect("EOF").data(); + + // set data from the eof to the shared memory. Padd it with zeros. + interpreter + .shared_memory + .set_data(mem_offset, offset, size, data); + } + *) + Definition data_copy (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 3) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop3_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let mem_offset := M.copy (| ฮณ0_0 |) in + let offset := M.copy (| ฮณ0_1 |) in + let size := M.copy (| ฮณ0_2 |) in + let~ size := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ size ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| size |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| M.read (| M.return_ (| Value.Tuple [] |) |) |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ mem_offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ mem_offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "usize", "saturating_add", [] |), + [ M.read (| mem_offset |); M.read (| size |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ offset := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ offset ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => + ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ data := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "data", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::bytecode::eof::Eof" ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "eof", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |); + M.read (| Value.String "EOF" |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set_data", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| mem_offset |); + M.read (| offset |); + M.read (| size |); + M.read (| data |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_data_copy : + M.IsFunction "revm_interpreter::instructions::data::data_copy" data_copy. + End data. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/host.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/host.md new file mode 100644 index 00000000..a98dc6de --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/host.md @@ -0,0 +1,5307 @@ +# ๐Ÿ“ host.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/host.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module host. + (* + pub fn balance(interpreter: &mut Interpreter, host: &mut H) { + pop_address!(interpreter, address); + let Some((balance, is_cold)) = host.balance(address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + gas!( + interpreter, + if SPEC::enabled(BERLIN) { + warm_cold_cost(is_cold) + } else if SPEC::enabled(ISTANBUL) { + // EIP-1884: Repricing for trie-size-dependent opcodes + 700 + } else if SPEC::enabled(TANGERINE) { + 400 + } else { + 20 + } + ); + push!(interpreter, balance); + } + *) + Definition balance (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ address := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| "revm_interpreter::host::Host", H, [], "balance", [] |), + [ M.read (| host |); M.read (| address |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let balance := M.copy (| ฮณ1_0 |) in + let is_cold := M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::warm_cold_cost", + [] + |), + [ M.read (| is_cold |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::ISTANBUL" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| Value.Integer 700 |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::TANGERINE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.Integer 400 + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Integer 20 + |))) + ] + |))) + ] + |))) + ] + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| balance |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_balance : M.IsFunction "revm_interpreter::instructions::host::balance" balance. + + (* + pub fn selfbalance(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, ISTANBUL); + gas!(interpreter, gas::LOW); + let Some((balance, _)) = host.balance(interpreter.contract.target_address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + push!(interpreter, balance); + } + *) + Definition selfbalance (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::ISTANBUL" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| "revm_interpreter::gas::constants::LOW" |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| "revm_interpreter::host::Host", H, [], "balance", [] |), + [ + M.read (| host |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let balance := M.copy (| ฮณ1_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| balance |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_selfbalance : + M.IsFunction "revm_interpreter::instructions::host::selfbalance" selfbalance. + + (* + pub fn extcodesize(interpreter: &mut Interpreter, host: &mut H) { + pop_address!(interpreter, address); + let Some((code, is_cold)) = host.code(address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + if SPEC::enabled(BERLIN) { + gas!(interpreter, warm_cold_cost(is_cold)); + } else if SPEC::enabled(TANGERINE) { + gas!(interpreter, 700); + } else { + gas!(interpreter, 20); + } + + push!(interpreter, U256::from(code.len())); + } + *) + Definition extcodesize (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ address := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| "revm_interpreter::host::Host", H, [], "code", [] |), + [ M.read (| host |); M.read (| address |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let code := M.copy (| ฮณ1_0 |) in + let is_cold := M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::warm_cold_cost", + [] + |), + [ M.read (| is_cold |) ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::TANGERINE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + Value.Integer 700 + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + Value.Integer 20 + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "len", + [] + |), + [ code ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_extcodesize : + M.IsFunction "revm_interpreter::instructions::host::extcodesize" extcodesize. + + (* + pub fn extcodehash(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CONSTANTINOPLE); + pop_address!(interpreter, address); + let Some((code_hash, is_cold)) = host.code_hash(address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + if SPEC::enabled(BERLIN) { + gas!(interpreter, warm_cold_cost(is_cold)); + } else if SPEC::enabled(ISTANBUL) { + gas!(interpreter, 700); + } else { + gas!(interpreter, 400); + } + push_b256!(interpreter, code_hash); + } + *) + Definition extcodehash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CONSTANTINOPLE" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ address := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "code_hash", + [] + |), + [ M.read (| host |); M.read (| address |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let code_hash := M.copy (| ฮณ1_0 |) in + let is_cold := M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::warm_cold_cost", + [] + |), + [ M.read (| is_cold |) ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::ISTANBUL" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + Value.Integer 700 + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + Value.Integer 400 + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_b256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| code_hash |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_extcodehash : + M.IsFunction "revm_interpreter::instructions::host::extcodehash" extcodehash. + + (* + pub fn extcodecopy(interpreter: &mut Interpreter, host: &mut H) { + pop_address!(interpreter, address); + pop!(interpreter, memory_offset, code_offset, len_u256); + + let Some((code, is_cold)) = host.code(address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + + let len = as_usize_or_fail!(interpreter, len_u256); + gas_or_fail!( + interpreter, + gas::extcodecopy_cost(SPEC::SPEC_ID, len as u64, is_cold) + ); + if len == 0 { + return; + } + let memory_offset = as_usize_or_fail!(interpreter, memory_offset); + let code_offset = min(as_usize_saturated!(code_offset), code.len()); + resize_memory!(interpreter, memory_offset, len); + + // Note: this can't panic because we resized memory to fit. + interpreter + .shared_memory + .set_data(memory_offset, code_offset, len, &code.original_bytes()); + } + *) + Definition extcodecopy (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ address := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 3) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop3_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let memory_offset := M.copy (| ฮณ0_0 |) in + let code_offset := M.copy (| ฮณ0_1 |) in + let len_u256 := M.copy (| ฮณ0_2 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "code", + [] + |), + [ M.read (| host |); M.read (| address |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let code := M.copy (| ฮณ1_0 |) in + let is_cold := M.copy (| ฮณ1_1 |) in + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ len_u256 ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::extcodecopy_cost", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::specification::Spec::SPEC_ID" + |) + |); + M.rust_cast (M.read (| len |)); + M.read (| is_cold |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.return_ (| Value.Tuple [] |) |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ memory_offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ memory_offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ code_offset := + M.alloc (| + M.call_closure (| + M.get_function (| "core::cmp::min", [ Ty.path "usize" ] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "usize"; + Ty.path "core::num::error::TryFromIntError" + ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ code_offset ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| + Value.Integer 1 + |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| + Value.Integer 2 + |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| + Value.Integer 3 + |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "len", + [] + |), + [ code ] + |) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| memory_offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set_data", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| memory_offset |); + M.read (| code_offset |); + M.read (| len |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "original_bytes", + [] + |), + [ code ] + |) + |) + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_extcodecopy : + M.IsFunction "revm_interpreter::instructions::host::extcodecopy" extcodecopy. + + (* + pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BLOCKHASH); + pop_top!(interpreter, number); + + let block_number = host.env().block.number; + + match block_number.checked_sub( *number) { + Some(diff) if !diff.is_zero() => { + let diff = as_usize_saturated!(diff); + + // blockhash should push zero if number is same as current block number. + if SPEC::enabled(PRAGUE) && diff <= BLOCKHASH_SERVE_WINDOW { + let value = sload!( + interpreter, + host, + BLOCKHASH_STORAGE_ADDRESS, + number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)) + ); + *number = value; + return; + } else if diff <= BLOCK_HASH_HISTORY { + let Some(hash) = host.block_hash( *number) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + *number = U256::from_be_bytes(hash.0); + return; + } + } + _ => { + // If blockhash is requested for the current block, the hash should be 0, so we fall + // through. + } + } + + *number = U256::ZERO; + } + *) + Definition blockhash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BLOCKHASH" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ number := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ block_number := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| "revm_interpreter::host::Host", H, [], "env", [] |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "number" + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "checked_sub", [] |), + [ M.read (| block_number |); M.read (| M.read (| number |) |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let diff := M.copy (| ฮณ0_0 |) in + let ฮณ := + M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "is_zero", + [] + |), + [ diff ] + |)) + |) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ diff := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" + ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ diff ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::PRAGUE" + [] + ] + |), + ltac:(M.monadic + (BinOp.Pure.le + (M.read (| diff |)) + (M.read (| + M.get_constant (| + "revm_primitives::constants::BLOCKHASH_SERVE_WINDOW" + |) + |)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ value := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "sload", + [] + |), + [ + M.read (| host |); + M.read (| + M.get_constant (| + "revm_primitives::constants::BLOCKHASH_STORAGE_ADDRESS" + |) + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "wrapping_rem", + [] + |), + [ + M.read (| M.read (| number |) |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "usize" ] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::constants::BLOCKHASH_SERVE_WINDOW" + |) + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let value := M.copy (| ฮณ1_0 |) in + let is_cold := M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + interpreter + |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::sload_cost", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::specification::Spec::SPEC_ID" + |) + |); + M.read (| is_cold |) + ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + value)) + ] + |) + |) in + let~ _ := + M.write (| M.read (| number |), M.read (| value |) |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.le + (M.read (| diff |)) + (M.read (| + M.get_constant (| + "revm_primitives::constants::BLOCK_HASH_HISTORY" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "block_hash", + [] + |), + [ + M.read (| host |); + M.read (| M.read (| number |) |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let hash := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.read (| number |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from_be_bytes", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_tuple_field (| + hash, + "alloy_primitives::bits::fixed::FixedBytes", + 0 + |) + |) + ] + |) + |) in + M.return_ (| Value.Tuple [] |))) + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.read (| number |), + M.read (| M.get_constant (| "ruint::ZERO" |) |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_blockhash : + M.IsFunction "revm_interpreter::instructions::host::blockhash" blockhash. + + (* + pub fn sload(interpreter: &mut Interpreter, host: &mut H) { + pop_top!(interpreter, index); + let value = sload!( + interpreter, + host, + interpreter.contract.target_address, + *index + ); + *index = value; + } + *) + Definition sload (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ index := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ value := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "sload", + [] + |), + [ + M.read (| host |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |); + M.read (| M.read (| index |) |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let value := M.copy (| ฮณ1_0 |) in + let is_cold := M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::sload_cost", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::specification::Spec::SPEC_ID" + |) + |); + M.read (| is_cold |) + ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + value)) + ] + |) + |) in + let~ _ := M.write (| M.read (| index |), M.read (| value |) |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sload : M.IsFunction "revm_interpreter::instructions::host::sload" sload. + + (* + pub fn sstore(interpreter: &mut Interpreter, host: &mut H) { + require_non_staticcall!(interpreter); + + pop!(interpreter, index, value); + let Some(SStoreResult { + original_value: original, + present_value: old, + new_value: new, + is_cold, + }) = host.sstore(interpreter.contract.target_address, index, value) + else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + gas_or_fail!(interpreter, { + let remaining_gas = interpreter.gas.remaining(); + gas::sstore_cost(SPEC::SPEC_ID, original, old, new, remaining_gas, is_cold) + }); + refund!( + interpreter, + gas::sstore_refund(SPEC::SPEC_ID, original, old, new) + ); + } + *) + Definition sstore (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let index := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "sstore", + [] + |), + [ + M.read (| host |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |); + M.read (| index |); + M.read (| value |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::host::SStoreResult", + "original_value" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::host::SStoreResult", + "present_value" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::host::SStoreResult", + "new_value" + |) in + let ฮณ1_3 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::host::SStoreResult", + "is_cold" + |) in + let original := M.copy (| ฮณ1_0 |) in + let old := M.copy (| ฮณ1_1 |) in + let new := M.copy (| ฮณ1_2 |) in + let is_cold := M.copy (| ฮณ1_3 |) in + let~ _ := + M.match_operator (| + let~ remaining_gas := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::sstore_cost", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::specification::Spec::SPEC_ID" + |) + |); + M.read (| original |); + M.read (| old |); + M.read (| new |); + M.read (| remaining_gas |); + M.read (| is_cold |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_refund", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::sstore_refund", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::specification::Spec::SPEC_ID" + |) + |); + M.read (| original |); + M.read (| old |); + M.read (| new |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sstore : M.IsFunction "revm_interpreter::instructions::host::sstore" sstore. + + (* + pub fn tstore(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CANCUN); + require_non_staticcall!(interpreter); + gas!(interpreter, gas::WARM_STORAGE_READ_COST); + + pop!(interpreter, index, value); + + host.tstore(interpreter.contract.target_address, index, value); + } + *) + Definition tstore (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CANCUN" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::WARM_STORAGE_READ_COST" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let index := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "tstore", + [] + |), + [ + M.read (| host |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |); + M.read (| index |); + M.read (| value |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_tstore : M.IsFunction "revm_interpreter::instructions::host::tstore" tstore. + + (* + pub fn tload(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CANCUN); + gas!(interpreter, gas::WARM_STORAGE_READ_COST); + + pop_top!(interpreter, index); + + *index = host.tload(interpreter.contract.target_address, *index); + } + *) + Definition tload (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CANCUN" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::WARM_STORAGE_READ_COST" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ index := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| index |), + M.call_closure (| + M.get_trait_method (| "revm_interpreter::host::Host", H, [], "tload", [] |), + [ + M.read (| host |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |); + M.read (| M.read (| index |) |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_tload : M.IsFunction "revm_interpreter::instructions::host::tload" tload. + + (* + pub fn log(interpreter: &mut Interpreter, host: &mut H) { + require_non_staticcall!(interpreter); + + pop!(interpreter, offset, len); + let len = as_usize_or_fail!(interpreter, len); + gas_or_fail!(interpreter, gas::log_cost(N as u8, len as u64)); + let data = if len == 0 { + Bytes::new() + } else { + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, len); + Bytes::copy_from_slice(interpreter.shared_memory.slice(offset, len)) + }; + + if interpreter.stack.len() < N { + interpreter.instruction_result = InstructionResult::StackUnderflow; + return; + } + + let mut topics = Vec::with_capacity(N); + for _ in 0..N { + // SAFETY: stack bounds already checked few lines above + topics.push(B256::from(unsafe { interpreter.stack.pop_unsafe() })); + } + + let log = Log { + address: interpreter.contract.target_address, + data: LogData::new(topics, data).expect("LogData should have <=4 topics"), + }; + + host.log(log); + } + *) + Definition log (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let offset := M.copy (| ฮณ0_0 |) in + let len := M.copy (| ฮณ0_1 |) in + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ len ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::log_cost", [] |), + [ + M.rust_cast + (M.read (| + M.get_constant (| + "revm_interpreter::instructions::host::log::N" + |) + |)); + M.rust_cast (M.read (| len |)) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ data := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let~ offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| offset |); + M.read (| len |) + ] + |) + ] + |) + |))) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (M.read (| + M.get_constant (| + "revm_interpreter::instructions::host::log::N" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ topics := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_interpreter::instructions::host::log::N" + |) + |) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", + M.read (| + M.get_constant (| + "revm_interpreter::instructions::host::log::N" + |) + |)) + ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + topics; + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path + "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ log := + M.alloc (| + Value.StructRecord + "alloy_primitives::log::Log" + [ + ("address", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |)); + ("data", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::log::LogData" ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::log::LogData", + "new", + [] + |), + [ M.read (| topics |); M.read (| data |) ] + |); + M.read (| Value.String "LogData should have <=4 topics" |) + ] + |)) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "log", + [] + |), + [ M.read (| host |); M.read (| log |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_log : M.IsFunction "revm_interpreter::instructions::host::log" log. + + (* + pub fn selfdestruct(interpreter: &mut Interpreter, host: &mut H) { + require_non_staticcall!(interpreter); + pop_address!(interpreter, target); + + let Some(res) = host.selfdestruct(interpreter.contract.target_address, target) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + + // EIP-3529: Reduction in refunds + if !SPEC::enabled(LONDON) && !res.previously_destroyed { + refund!(interpreter, gas::SELFDESTRUCT) + } + gas!(interpreter, gas::selfdestruct_cost(SPEC::SPEC_ID, res)); + + interpreter.instruction_result = InstructionResult::SelfDestruct; + } + *) + Definition selfdestruct (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ target := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "from_word", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "selfdestruct", + [] + |), + [ + M.read (| host |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + |); + M.read (| target |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let res := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::LONDON" + [] + ] + |)), + ltac:(M.monadic + (UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + res, + "revm_interpreter::host::SelfDestructResult", + "previously_destroyed" + |) + |)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_refund", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::SELFDESTRUCT" + |) + |) + ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::selfdestruct_cost", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::specification::Spec::SPEC_ID" + |) + |); + M.read (| res |) + ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_selfdestruct : + M.IsFunction "revm_interpreter::instructions::host::selfdestruct" selfdestruct. + End host. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/host_env.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/host_env.md new file mode 100644 index 00000000..25c4d73e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/host_env.md @@ -0,0 +1,2220 @@ +# ๐Ÿ“ host_env.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/host_env.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module host_env. + (* + pub fn chainid(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, ISTANBUL); + gas!(interpreter, gas::BASE); + push!(interpreter, U256::from(host.env().cfg.chain_id)); + } + *) + Definition chainid (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::ISTANBUL" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "cfg" + |), + "revm_primitives::env::CfgEnv", + "chain_id" + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_chainid : + M.IsFunction "revm_interpreter::instructions::host_env::chainid" chainid. + + (* + pub fn coinbase(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push_b256!(interpreter, host.env().block.coinbase.into_word()); + } + *) + Definition coinbase (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_b256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "into_word", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "coinbase" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_coinbase : + M.IsFunction "revm_interpreter::instructions::host_env::coinbase" coinbase. + + (* + pub fn timestamp(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().block.timestamp); + } + *) + Definition timestamp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "timestamp" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_timestamp : + M.IsFunction "revm_interpreter::instructions::host_env::timestamp" timestamp. + + (* + pub fn block_number(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().block.number); + } + *) + Definition block_number (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "number" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_block_number : + M.IsFunction "revm_interpreter::instructions::host_env::block_number" block_number. + + (* + pub fn difficulty(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + if SPEC::enabled(MERGE) { + push_b256!(interpreter, host.env().block.prevrandao.unwrap()); + } else { + push!(interpreter, host.env().block.difficulty); + } + } + *) + Definition difficulty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::MERGE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_b256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "unwrap", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "prevrandao" + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "difficulty" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_difficulty : + M.IsFunction "revm_interpreter::instructions::host_env::difficulty" difficulty. + + (* + pub fn gaslimit(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().block.gas_limit); + } + *) + Definition gaslimit (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "gas_limit" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_gaslimit : + M.IsFunction "revm_interpreter::instructions::host_env::gaslimit" gaslimit. + + (* + pub fn gasprice(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().effective_gas_price()); + } + *) + Definition gasprice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "effective_gas_price", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_gasprice : + M.IsFunction "revm_interpreter::instructions::host_env::gasprice" gasprice. + + (* + pub fn basefee(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, LONDON); + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().block.basefee); + } + *) + Definition basefee (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::LONDON" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "basefee" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_basefee : + M.IsFunction "revm_interpreter::instructions::host_env::basefee" basefee. + + (* + pub fn origin(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push_b256!(interpreter, host.env().tx.caller.into_word()); + } + *) + Definition origin (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_b256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "into_word", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "caller" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_origin : M.IsFunction "revm_interpreter::instructions::host_env::origin" origin. + + (* + pub fn blob_hash(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CANCUN); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, index); + let i = as_usize_saturated!(index); + *index = match host.env().tx.blob_hashes.get(i) { + Some(hash) => U256::from_be_bytes(hash.0), + None => U256::ZERO, + }; + } + *) + Definition blob_hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CANCUN" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ index := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ i := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ M.read (| index |) ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| index |), + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "get", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |) + ] + |); + M.read (| i |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let hash := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from_be_bytes", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_tuple_field (| + M.read (| hash |), + "alloy_primitives::bits::fixed::FixedBytes", + 0 + |) + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.get_constant (| "ruint::ZERO" |))) + ] + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_blob_hash : + M.IsFunction "revm_interpreter::instructions::host_env::blob_hash" blob_hash. + + (* + pub fn blob_basefee(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CANCUN); + gas!(interpreter, gas::BASE); + push!( + interpreter, + U256::from(host.env().block.get_blob_gasprice().unwrap_or_default()) + ); + } + *) + Definition blob_basefee (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CANCUN" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u128" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "u128" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::BlockEnv", + "get_blob_gasprice", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + H, + [], + "env", + [] + |), + [ M.read (| host |) ] + |), + "revm_primitives::env::Env", + "block" + |) + ] + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_blob_basefee : + M.IsFunction "revm_interpreter::instructions::host_env::blob_basefee" blob_basefee. + End host_env. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/i256.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/i256.md new file mode 100644 index 00000000..b30e0303 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/i256.md @@ -0,0 +1,1209 @@ +# ๐Ÿ“ i256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/i256.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module i256. + (* + Enum Sign + { + ty_params := []; + variants := + [ + { + name := "Minus"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Zero"; + item := StructTuple []; + discriminant := Some 0; + }; + { + name := "Plus"; + item := StructTuple []; + discriminant := Some 1; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_instructions_i256_Sign. + + Module Impl_core_marker_Copy_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_instructions_i256_Sign. + + Module Impl_core_fmt_Debug_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instructions::i256::Sign::Minus" + |) in + M.alloc (| M.read (| Value.String "Minus" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instructions::i256::Sign::Zero" + |) in + M.alloc (| M.read (| Value.String "Zero" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instructions::i256::Sign::Plus" + |) in + M.alloc (| M.read (| Value.String "Plus" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_instructions_i256_Sign. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_instructions_i256_Sign. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_instructions_i256_Sign. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_instructions_i256_Sign. + + Module Impl_core_cmp_Eq_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_instructions_i256_Sign. + + Module Impl_core_cmp_PartialOrd_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "i8", + [ Ty.path "i8" ], + "partial_cmp", + [] + |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_interpreter_instructions_i256_Sign. + + Module Impl_core_cmp_Ord_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "i8", [], "cmp", [] |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_interpreter_instructions_i256_Sign. + + Module Impl_core_hash_Hash_for_revm_interpreter_instructions_i256_Sign. + Definition Self : Ty.t := Ty.path "revm_interpreter::instructions::i256::Sign". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "i8", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_instructions_i256_Sign. + + Definition value_MAX_POSITIVE_VALUE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from_limbs", [] |), + [ + Value.Array + [ + Value.Integer 18446744073709551615; + Value.Integer 18446744073709551615; + Value.Integer 18446744073709551615; + Value.Integer 9223372036854775807 + ] + ] + |) + |))). + + Definition value_MIN_NEGATIVE_VALUE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from_limbs", [] |), + [ + Value.Array + [ + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 9223372036854775808 + ] + ] + |) + |))). + + Definition value_FLIPH_BITMASK_U64 : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 9223372036854775807 |))). + + (* + pub fn i256_sign(val: &U256) -> Sign { + if val.bit(U256::BITS - 1) { + Sign::Minus + } else { + // SAFETY: false == 0 == Zero, true == 1 == Plus + unsafe { core::mem::transmute( *val != U256::ZERO) } + } + } + *) + Definition i256_sign (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ val ] => + ltac:(M.monadic + (let val := M.alloc (| val |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "bit", [] |), + [ + M.read (| val |); + BinOp.Wrap.sub + Integer.Usize + (M.read (| M.get_constant (| "ruint::BITS'1" |) |)) + (Value.Integer 1) + ] + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + Value.StructTuple "revm_interpreter::instructions::i256::Sign::Minus" [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::transmute", + [ Ty.path "bool"; Ty.path "revm_interpreter::instructions::i256::Sign" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ M.read (| val |); M.get_constant (| "ruint::ZERO" |) ] + |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_i256_sign : + M.IsFunction "revm_interpreter::instructions::i256::i256_sign" i256_sign. + + (* + pub fn i256_sign_compl(val: &mut U256) -> Sign { + let sign = i256_sign(val); + if sign == Sign::Minus { + two_compl_mut(val); + } + sign + } + *) + Definition i256_sign_compl (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ val ] => + ltac:(M.monadic + (let val := M.alloc (| val |) in + M.read (| + let~ sign := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::instructions::i256::i256_sign", [] |), + [ M.read (| val |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instructions::i256::Sign", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ], + "eq", + [] + |), + [ + sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Minus" + [] + |) + ] + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::two_compl_mut", + [] + |), + [ M.read (| val |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + sign + |))) + | _, _ => M.impossible + end. + + Axiom Function_i256_sign_compl : + M.IsFunction "revm_interpreter::instructions::i256::i256_sign_compl" i256_sign_compl. + + (* + fn u256_remove_sign(val: &mut U256) { + // SAFETY: U256 does not have any padding bytes + unsafe { + val.as_limbs_mut()[3] &= FLIPH_BITMASK_U64; + } + } + *) + Definition u256_remove_sign (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ val ] => + ltac:(M.monadic + (let val := M.alloc (| val |) in + M.read (| + let~ _ := + let ฮฒ := + M.SubPointer.get_array_field (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "as_limbs_mut", [] |), + [ M.read (| val |) ] + |), + M.alloc (| Value.Integer 3 |) + |) in + M.write (| + ฮฒ, + BinOp.Pure.bit_and + (M.read (| ฮฒ |)) + (M.read (| + M.get_constant (| "revm_interpreter::instructions::i256::FLIPH_BITMASK_U64" |) + |)) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_u256_remove_sign : + M.IsFunction "revm_interpreter::instructions::i256::u256_remove_sign" u256_remove_sign. + + (* + pub fn two_compl_mut(op: &mut U256) { + *op = two_compl( *op); + } + *) + Definition two_compl_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ op ] => + ltac:(M.monadic + (let op := M.alloc (| op |) in + M.read (| + let~ _ := + M.write (| + M.read (| op |), + M.call_closure (| + M.get_function (| "revm_interpreter::instructions::i256::two_compl", [] |), + [ M.read (| M.read (| op |) |) ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_two_compl_mut : + M.IsFunction "revm_interpreter::instructions::i256::two_compl_mut" two_compl_mut. + + (* + pub fn two_compl(op: U256) -> U256 { + op.wrapping_neg() + } + *) + Definition two_compl (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ op ] => + ltac:(M.monadic + (let op := M.alloc (| op |) in + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "wrapping_neg", [] |), + [ M.read (| op |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_two_compl : + M.IsFunction "revm_interpreter::instructions::i256::two_compl" two_compl. + + (* + pub fn i256_cmp(first: &U256, second: &U256) -> Ordering { + let first_sign = i256_sign(first); + let second_sign = i256_sign(second); + match first_sign.cmp(&second_sign) { + // note: adding `if first_sign != Sign::Zero` to short circuit zero comparisons performs + // slower on average, as of #582 + Ordering::Equal => first.cmp(second), + o => o, + } + } + *) + Definition i256_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ first; second ] => + ltac:(M.monadic + (let first := M.alloc (| first |) in + let second := M.alloc (| second |) in + M.read (| + let~ first_sign := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::instructions::i256::i256_sign", [] |), + [ M.read (| first |) ] + |) + |) in + let~ second_sign := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::instructions::i256::i256_sign", [] |), + [ M.read (| second |) ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "revm_interpreter::instructions::i256::Sign", + [], + "cmp", + [] + |), + [ first_sign; second_sign ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::cmp::Ordering::Equal" |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "ruint::Uint", + [], + "cmp", + [] + |), + [ M.read (| first |); M.read (| second |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let o := M.copy (| ฮณ |) in + o)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_i256_cmp : + M.IsFunction "revm_interpreter::instructions::i256::i256_cmp" i256_cmp. + + (* + pub fn i256_div(mut first: U256, mut second: U256) -> U256 { + let second_sign = i256_sign_compl(&mut second); + if second_sign == Sign::Zero { + return U256::ZERO; + } + + let first_sign = i256_sign_compl(&mut first); + if first == MIN_NEGATIVE_VALUE && second == U256::from(1) { + return two_compl(MIN_NEGATIVE_VALUE); + } + + // necessary overflow checks are done above, perform the division + let mut d = first / second; + + // set sign bit to zero + u256_remove_sign(&mut d); + + // two's complement only if the signs are different + // note: this condition has better codegen than an exhaustive match, as of #582 + if (first_sign == Sign::Minus && second_sign != Sign::Minus) + || (second_sign == Sign::Minus && first_sign != Sign::Minus) + { + two_compl(d) + } else { + d + } + } + *) + Definition i256_div (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ first; second ] => + ltac:(M.monadic + (let first := M.alloc (| first |) in + let second := M.alloc (| second |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ second_sign := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::i256_sign_compl", + [] + |), + [ second ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instructions::i256::Sign", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ], + "eq", + [] + |), + [ + second_sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Zero" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| M.read (| M.get_constant (| "ruint::ZERO" |) |) |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ first_sign := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::i256_sign_compl", + [] + |), + [ first ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + first; + M.get_constant (| + "revm_interpreter::instructions::i256::MIN_NEGATIVE_VALUE" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + second; + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 1 ] + |) + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::two_compl", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_interpreter::instructions::i256::MIN_NEGATIVE_VALUE" + |) + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ d := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Div", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "div", + [] + |), + [ M.read (| first |); M.read (| second |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::u256_remove_sign", + [] + |), + [ d ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instructions::i256::Sign", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ], + "eq", + [] + |), + [ + first_sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Minus" + [] + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instructions::i256::Sign", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ], + "ne", + [] + |), + [ + second_sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Minus" + [] + |) + ] + |))) + |), + ltac:(M.monadic + (LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instructions::i256::Sign", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ], + "eq", + [] + |), + [ + second_sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Minus" + [] + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instructions::i256::Sign", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ], + "ne", + [] + |), + [ + first_sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Minus" + [] + |) + ] + |))) + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::two_compl", + [] + |), + [ M.read (| d |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic d) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_i256_div : + M.IsFunction "revm_interpreter::instructions::i256::i256_div" i256_div. + + (* + pub fn i256_mod(mut first: U256, mut second: U256) -> U256 { + let first_sign = i256_sign_compl(&mut first); + if first_sign == Sign::Zero { + return U256::ZERO; + } + + let second_sign = i256_sign_compl(&mut second); + if second_sign == Sign::Zero { + return U256::ZERO; + } + + let mut r = first % second; + + // set sign bit to zero + u256_remove_sign(&mut r); + + if first_sign == Sign::Minus { + two_compl(r) + } else { + r + } + } + *) + Definition i256_mod (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ first; second ] => + ltac:(M.monadic + (let first := M.alloc (| first |) in + let second := M.alloc (| second |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ first_sign := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::i256_sign_compl", + [] + |), + [ first ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instructions::i256::Sign", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ], + "eq", + [] + |), + [ + first_sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Zero" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| M.read (| M.get_constant (| "ruint::ZERO" |) |) |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ second_sign := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::i256_sign_compl", + [] + |), + [ second ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instructions::i256::Sign", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ], + "eq", + [] + |), + [ + second_sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Zero" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| M.read (| M.get_constant (| "ruint::ZERO" |) |) |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ r := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Rem", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "rem", + [] + |), + [ M.read (| first |); M.read (| second |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::u256_remove_sign", + [] + |), + [ r ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instructions::i256::Sign", + [ Ty.path "revm_interpreter::instructions::i256::Sign" ], + "eq", + [] + |), + [ + first_sign; + M.alloc (| + Value.StructTuple + "revm_interpreter::instructions::i256::Sign::Minus" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::i256::two_compl", + [] + |), + [ M.read (| r |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic r) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_i256_mod : + M.IsFunction "revm_interpreter::instructions::i256::i256_mod" i256_mod. + End i256. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/memory.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/memory.md new file mode 100644 index 00000000..0ac841b6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/memory.md @@ -0,0 +1,2046 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/memory.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module memory. + (* + pub fn mload(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, top); + let offset = as_usize_or_fail!(interpreter, top); + resize_memory!(interpreter, offset, 32); + *top = interpreter.shared_memory.get_u256(offset); + } + *) + Definition mload (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ top := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "as_limbs", [] |), + [ M.read (| top |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "usize", "saturating_add", [] |), + [ M.read (| offset |); Value.Integer 32 ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.read (| top |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "get_u256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| offset |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_mload : M.IsFunction "revm_interpreter::instructions::memory::mload" mload. + + (* + pub fn mstore(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop!(interpreter, offset, value); + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, 32); + interpreter.shared_memory.set_u256(offset, value); + } + *) + Definition mstore (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let offset := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + let~ offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "usize", "saturating_add", [] |), + [ M.read (| offset |); Value.Integer 32 ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set_u256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| offset |); + M.read (| value |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_mstore : M.IsFunction "revm_interpreter::instructions::memory::mstore" mstore. + + (* + pub fn mstore8(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop!(interpreter, offset, value); + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, 1); + interpreter.shared_memory.set_byte(offset, value.byte(0)) + } + *) + Definition mstore8 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop2_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let offset := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + let~ offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "usize", "saturating_add", [] |), + [ M.read (| offset |); Value.Integer 1 ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set_byte", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| offset |); + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "byte", [] |), + [ value; Value.Integer 0 ] + |) + ] + |) + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_mstore8 : M.IsFunction "revm_interpreter::instructions::memory::mstore8" mstore8. + + (* + pub fn msize(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, U256::from(interpreter.shared_memory.len())); + } + *) + Definition msize (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_msize : M.IsFunction "revm_interpreter::instructions::memory::msize" msize. + + (* + pub fn mcopy(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, CANCUN); + pop!(interpreter, dst, src, len); + + // into usize or fail + let len = as_usize_or_fail!(interpreter, len); + // deduce gas + gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); + if len == 0 { + return; + } + + let dst = as_usize_or_fail!(interpreter, dst); + let src = as_usize_or_fail!(interpreter, src); + // resize memory + resize_memory!(interpreter, max(dst, src), len); + // copy memory in place + interpreter.shared_memory.copy(dst, src, len); + } + *) + Definition mcopy (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CANCUN" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 3) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop3_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let dst := M.copy (| ฮณ0_0 |) in + let src := M.copy (| ฮณ0_1 |) in + let len := M.copy (| ฮณ0_2 |) in + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ len ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::verylowcopy_cost", + [] + |), + [ M.rust_cast (M.read (| len |)) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| M.read (| M.return_ (| Value.Tuple [] |) |) |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ dst := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ dst ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ src := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ src ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "usize", "saturating_add", [] |), + [ + M.call_closure (| + M.get_function (| "core::cmp::max", [ Ty.path "usize" ] |), + [ M.read (| dst |); M.read (| src |) ] + |); + M.read (| len |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "copy", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| dst |); + M.read (| src |); + M.read (| len |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_mcopy : M.IsFunction "revm_interpreter::instructions::memory::mcopy" mcopy. + End memory. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/stack.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/stack.md new file mode 100644 index 00000000..f135d0d4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/stack.md @@ -0,0 +1,1354 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/stack.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module stack. + (* + pub fn pop(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + if let Err(result) = interpreter.stack.pop() { + interpreter.instruction_result = result; + } + } + *) + Definition pop (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| result |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_pop : M.IsFunction "revm_interpreter::instructions::stack::pop" pop. + + (* + pub fn push0(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, SHANGHAI); + gas!(interpreter, gas::BASE); + if let Err(result) = interpreter.stack.push(U256::ZERO) { + interpreter.instruction_result = result; + } + } + *) + Definition push0 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::SHANGHAI" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| M.get_constant (| "ruint::ZERO" |) |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| result |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_push0 : M.IsFunction "revm_interpreter::instructions::stack::push0" push0. + + (* + pub fn push(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + // SAFETY: In analysis we append trailing bytes to the bytecode so that this is safe to do + // without bounds checking. + let ip = interpreter.instruction_pointer; + if let Err(result) = interpreter + .stack + .push_slice(unsafe { core::slice::from_raw_parts(ip, N) }) + { + interpreter.instruction_result = result; + return; + } + interpreter.instruction_pointer = unsafe { ip.add(N) }; + } + *) + Definition push (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ ip := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_slice", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_function (| + "core::slice::raw::from_raw_parts", + [ Ty.path "u8" ] + |), + [ + M.read (| ip |); + M.read (| + M.get_constant (| + "revm_interpreter::instructions::stack::push::N" + |) + |) + ] + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| result |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "add", + [] + |), + [ + M.read (| ip |); + M.read (| + M.get_constant (| "revm_interpreter::instructions::stack::push::N" |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_push : M.IsFunction "revm_interpreter::instructions::stack::push" push. + + (* + pub fn dup(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + if let Err(result) = interpreter.stack.dup(N) { + interpreter.instruction_result = result; + } + } + *) + Definition dup (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "dup", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.get_constant (| + "revm_interpreter::instructions::stack::dup::N" + |) + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| result |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_dup : M.IsFunction "revm_interpreter::instructions::stack::dup" dup. + + (* + pub fn swap(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + if let Err(result) = interpreter.stack.swap(N) { + interpreter.instruction_result = result; + } + } + *) + Definition swap (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "swap", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.get_constant (| + "revm_interpreter::instructions::stack::swap::N" + |) + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| result |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_swap : M.IsFunction "revm_interpreter::instructions::stack::swap" swap. + + (* + pub fn dupn(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::VERYLOW); + let imm = unsafe { *interpreter.instruction_pointer }; + if let Err(result) = interpreter.stack.dup(imm as usize + 1) { + interpreter.instruction_result = result; + } + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) }; + } + *) + Definition dupn (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ imm := + M.copy (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "dup", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + BinOp.Wrap.add + Integer.Usize + (M.rust_cast (M.read (| imm |))) + (Value.Integer 1) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| result |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + Value.Integer 1 + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_dupn : M.IsFunction "revm_interpreter::instructions::stack::dupn" dupn. + + (* + pub fn swapn(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::VERYLOW); + let imm = unsafe { *interpreter.instruction_pointer }; + if let Err(result) = interpreter.stack.swap(imm as usize + 1) { + interpreter.instruction_result = result; + } + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) }; + } + *) + Definition swapn (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ imm := + M.copy (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "swap", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + BinOp.Wrap.add + Integer.Usize + (M.rust_cast (M.read (| imm |))) + (Value.Integer 1) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| result |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + Value.Integer 1 + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_swapn : M.IsFunction "revm_interpreter::instructions::stack::swapn" swapn. + + (* + pub fn exchange(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::VERYLOW); + let imm = unsafe { *interpreter.instruction_pointer }; + let n = (imm >> 4) + 1; + let m = (imm & 0x0F) + 1; + if let Err(result) = interpreter.stack.exchange(n as usize, m as usize) { + interpreter.instruction_result = result; + } + + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) }; + } + *) + Definition exchange (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ imm := + M.copy (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + |) in + let~ n := + M.alloc (| + BinOp.Wrap.add + Integer.U8 + (BinOp.Wrap.shr (M.read (| imm |)) (Value.Integer 4)) + (Value.Integer 1) + |) in + let~ m := + M.alloc (| + BinOp.Wrap.add + Integer.U8 + (BinOp.Pure.bit_and (M.read (| imm |)) (Value.Integer 15)) + (Value.Integer 1) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "exchange", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.rust_cast (M.read (| n |)); + M.rust_cast (M.read (| m |)) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| result |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + Value.Integer 1 + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_exchange : + M.IsFunction "revm_interpreter::instructions::stack::exchange" exchange. + End stack. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/system.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/system.md new file mode 100644 index 00000000..53f92b4c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/system.md @@ -0,0 +1,5231 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/system.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module system. + (* + pub fn keccak256(interpreter: &mut Interpreter, _host: &mut H) { + pop_top!(interpreter, offset, len_ptr); + let len = as_usize_or_fail!(interpreter, len_ptr); + gas_or_fail!(interpreter, gas::keccak256_cost(len as u64)); + let hash = if len == 0 { + KECCAK_EMPTY + } else { + let from = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, from, len); + crate::primitives::keccak256(interpreter.shared_memory.slice(from, len)) + }; + *len_ptr = hash.into(); + } + *) + Definition keccak256 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let offset := M.copy (| ฮณ0_0 |) in + let len_ptr := M.copy (| ฮณ0_1 |) in + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ M.read (| len_ptr |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::keccak256_cost", + [] + |), + [ M.rust_cast (M.read (| len |)) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ hash := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.get_constant (| + "revm_primitives::utilities::KECCAK_EMPTY" + |))); + fun ฮณ => + ltac:(M.monadic + (let~ from := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| from |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "alloy_primitives::utils::keccak256", + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| from |); + M.read (| len |) + ] + |) + ] + |) + |))) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| len_ptr |), + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "into", + [] + |), + [ M.read (| hash |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_keccak256 : + M.IsFunction "revm_interpreter::instructions::system::keccak256" keccak256. + + (* + pub fn address(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push_b256!(interpreter, interpreter.contract.target_address.into_word()); + } + *) + Definition address (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_b256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "into_word", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_address : M.IsFunction "revm_interpreter::instructions::system::address" address. + + (* + pub fn caller(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push_b256!(interpreter, interpreter.contract.caller.into_word()); + } + *) + Definition caller (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_b256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "into_word", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "caller" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_caller : M.IsFunction "revm_interpreter::instructions::system::caller" caller. + + (* + pub fn codesize(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + // Inform the optimizer that the bytecode cannot be EOF to remove a bounds check. + assume!(!interpreter.contract.bytecode.is_eof()); + push!(interpreter, U256::from(interpreter.contract.bytecode.len())); + } + *) + Definition codesize (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "is_eof", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |))) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic_fmt", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: !interpreter.contract.bytecode.is_eof()" + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "none", + [] + |), + [] + |) + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::hint::unreachable_unchecked", + [] + |), + [] + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_codesize : + M.IsFunction "revm_interpreter::instructions::system::codesize" codesize. + + (* + pub fn codecopy(interpreter: &mut Interpreter, _host: &mut H) { + pop!(interpreter, memory_offset, code_offset, len); + let len = as_usize_or_fail!(interpreter, len); + gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); + if len == 0 { + return; + } + let memory_offset = as_usize_or_fail!(interpreter, memory_offset); + let code_offset = as_usize_saturated!(code_offset); + resize_memory!(interpreter, memory_offset, len); + + // Inform the optimizer that the bytecode cannot be EOF to remove a bounds check. + assume!(!interpreter.contract.bytecode.is_eof()); + // Note: this can't panic because we resized memory to fit. + interpreter.shared_memory.set_data( + memory_offset, + code_offset, + len, + &interpreter.contract.bytecode.original_bytes(), + ); + } + *) + Definition codecopy (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 3) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop3_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let memory_offset := M.copy (| ฮณ0_0 |) in + let code_offset := M.copy (| ฮณ0_1 |) in + let len := M.copy (| ฮณ0_2 |) in + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ len ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::verylowcopy_cost", + [] + |), + [ M.rust_cast (M.read (| len |)) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| M.read (| M.return_ (| Value.Tuple [] |) |) |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ memory_offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ memory_offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ code_offset := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ code_offset ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => + ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "usize", "saturating_add", [] |), + [ M.read (| memory_offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "is_eof", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic_fmt", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: !interpreter.contract.bytecode.is_eof()" + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "none", + [] + |), + [] + |) + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::hint::unreachable_unchecked", + [] + |), + [] + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set_data", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| memory_offset |); + M.read (| code_offset |); + M.read (| len |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "original_bytes", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |) + |) + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_codecopy : + M.IsFunction "revm_interpreter::instructions::system::codecopy" codecopy. + + (* + pub fn calldataload(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, offset_ptr); + let mut word = B256::ZERO; + let offset = as_usize_saturated!(offset_ptr); + if offset < interpreter.contract.input.len() { + let count = 32.min(interpreter.contract.input.len() - offset); + // SAFETY: count is bounded by the calldata length. + // This is `word[..count].copy_from_slice(input[offset..offset + count])`, written using + // raw pointers as apparently the compiler cannot optimize the slice version, and using + // `get_unchecked` twice is uglier. + debug_assert!(count <= 32 && offset + count <= interpreter.contract.input.len()); + unsafe { + ptr::copy_nonoverlapping( + interpreter.contract.input.as_ptr().add(offset), + word.as_mut_ptr(), + count, + ) + }; + } + *offset_ptr = word.into(); + } + *) + Definition calldataload (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ offset_ptr := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ word := + M.copy (| M.get_constant (| "alloy_primitives::bits::fixed::ZERO" |) |) in + let~ offset := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ M.read (| offset_ptr |) ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.read (| offset |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "input" + |) + ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ count := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "usize", + [], + "min", + [] + |), + [ + Value.Integer 32; + BinOp.Wrap.sub + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "input" + |) + ] + |) + ] + |)) + (M.read (| offset |)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.and (| + BinOp.Pure.le + (M.read (| count |)) + (Value.Integer 32), + ltac:(M.monadic + (BinOp.Pure.le + (BinOp.Wrap.add + Integer.Usize + (M.read (| offset |)) + (M.read (| count |))) + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path + "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "input" + |) + ] + |) + ] + |)))) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic", + [] + |), + [ + M.read (| + Value.String + "assertion failed: count <= 32 && offset + count <= interpreter.contract.input.len()" + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::copy_nonoverlapping", + [ Ty.path "u8" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "input" + |) + ] + |) + ] + |) + ] + |); + M.read (| offset |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_mut_ptr", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [], + "deref_mut", + [] + |), + [ word ] + |)) + ] + |); + M.read (| count |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.read (| offset_ptr |), + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "into", + [] + |), + [ M.read (| word |) ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_calldataload : + M.IsFunction "revm_interpreter::instructions::system::calldataload" calldataload. + + (* + pub fn calldatasize(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, U256::from(interpreter.contract.input.len())); + } + *) + Definition calldatasize (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "input" + |) + ] + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_calldatasize : + M.IsFunction "revm_interpreter::instructions::system::calldatasize" calldatasize. + + (* + pub fn callvalue(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, interpreter.contract.call_value); + } + *) + Definition callvalue (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "call_value" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_callvalue : + M.IsFunction "revm_interpreter::instructions::system::callvalue" callvalue. + + (* + pub fn calldatacopy(interpreter: &mut Interpreter, _host: &mut H) { + pop!(interpreter, memory_offset, data_offset, len); + let len = as_usize_or_fail!(interpreter, len); + gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); + if len == 0 { + return; + } + let memory_offset = as_usize_or_fail!(interpreter, memory_offset); + let data_offset = as_usize_saturated!(data_offset); + resize_memory!(interpreter, memory_offset, len); + + // Note: this can't panic because we resized memory to fit. + interpreter.shared_memory.set_data( + memory_offset, + data_offset, + len, + &interpreter.contract.input, + ); + } + *) + Definition calldatacopy (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 3) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop3_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let memory_offset := M.copy (| ฮณ0_0 |) in + let data_offset := M.copy (| ฮณ0_1 |) in + let len := M.copy (| ฮณ0_2 |) in + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ len ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::verylowcopy_cost", + [] + |), + [ M.rust_cast (M.read (| len |)) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| M.read (| M.return_ (| Value.Tuple [] |) |) |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ memory_offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ memory_offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ data_offset := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ data_offset ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => + ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "usize", "saturating_add", [] |), + [ M.read (| memory_offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set_data", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| memory_offset |); + M.read (| data_offset |); + M.read (| len |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "input" + |) + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_calldatacopy : + M.IsFunction "revm_interpreter::instructions::system::calldatacopy" calldatacopy. + + (* + pub fn returndatasize(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, BYZANTIUM); + gas!(interpreter, gas::BASE); + push!( + interpreter, + U256::from(interpreter.return_data_buffer.len()) + ); + } + *) + Definition returndatasize (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::BYZANTIUM" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |) + ] + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_returndatasize : + M.IsFunction "revm_interpreter::instructions::system::returndatasize" returndatasize. + + (* + pub fn returndatacopy(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, BYZANTIUM); + pop!(interpreter, memory_offset, offset, len); + let len = as_usize_or_fail!(interpreter, len); + gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); + let data_offset = as_usize_saturated!(offset); + let data_end = data_offset.saturating_add(len); + if data_end > interpreter.return_data_buffer.len() { + interpreter.instruction_result = InstructionResult::OutOfOffset; + return; + } + if len != 0 { + let memory_offset = as_usize_or_fail!(interpreter, memory_offset); + resize_memory!(interpreter, memory_offset, len); + interpreter.shared_memory.set( + memory_offset, + &interpreter.return_data_buffer[data_offset..data_end], + ); + } + } + *) + Definition returndatacopy (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::BYZANTIUM" + [] + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::NotActivated" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 3) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop3_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let memory_offset := M.copy (| ฮณ0_0 |) in + let offset := M.copy (| ฮณ0_1 |) in + let len := M.copy (| ฮณ0_2 |) in + let~ len := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ len ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::verylowcopy_cost", + [] + |), + [ M.rust_cast (M.read (| len |)) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| gas_used |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ data_offset := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::TryFromIntError" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ offset ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |))); + fun ฮณ => + ltac:(M.monadic (M.get_constant (| "core::num::MAX" |))) + ] + |) + |) + ] + |); + M.read (| M.get_constant (| "core::num::MAX" |) |) + ] + |) + |) in + let~ data_end := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "usize", "saturating_add", [] |), + [ M.read (| data_offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| data_end |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |) + ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfOffset" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne (M.read (| len |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ memory_offset := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "as_limbs", + [] + |), + [ memory_offset ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ new_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| memory_offset |); M.read (| len |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_size |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::resize_memory", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::MemoryOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| memory_offset |); + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |) + ] + |) + ] + |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| data_offset |)); + ("end_", M.read (| data_end |)) + ] + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_returndatacopy : + M.IsFunction "revm_interpreter::instructions::system::returndatacopy" returndatacopy. + + (* + pub fn returndataload(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, offset); + let offset_usize = as_usize_or_fail!(interpreter, offset); + if offset_usize.saturating_add(32) > interpreter.return_data_buffer.len() { + // TODO(EOF) proper error. + interpreter.instruction_result = InstructionResult::OutOfOffset; + return; + } + *offset = + B256::from_slice(&interpreter.return_data_buffer[offset_usize..offset_usize + 32]).into(); + } + *) + Definition returndataload (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::VERYLOW" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ offset := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) in + let~ offset_usize := + M.copy (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "as_limbs", [] |), + [ M.read (| offset |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 1 |) + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 2 |) + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 3 |) + |) + |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "u64" ], + "try_from", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| x |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| offset_usize |); Value.Integer 32 ] + |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |) + ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfOffset" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.read (| offset |), + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "into", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + "from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |) + ] + |) + ] + |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| offset_usize |)); + ("end_", + BinOp.Wrap.add + Integer.Usize + (M.read (| offset_usize |)) + (Value.Integer 32)) + ] + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_returndataload : + M.IsFunction "revm_interpreter::instructions::system::returndataload" returndataload. + + (* + pub fn gas(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, U256::from(interpreter.gas.remaining())); + } + *) + Definition gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ interpreter; _host ] => + ltac:(M.monadic + (let interpreter := M.alloc (| interpreter |) in + let _host := M.alloc (| _host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| + M.get_constant (| + "revm_interpreter::gas::constants::BASE" + |) + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_gas : M.IsFunction "revm_interpreter::instructions::system::gas" gas. + End system. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/utility.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/utility.md new file mode 100644 index 00000000..0d9a68f2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/instructions/utility.md @@ -0,0 +1,112 @@ +# ๐Ÿ“ utility.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/instructions/utility.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module instructions. + Module utility. + (* + pub(crate) unsafe fn read_i16(ptr: *const u8) -> i16 { + i16::from_be_bytes(core::slice::from_raw_parts(ptr, 2).try_into().unwrap()) + } + *) + Definition read_i16 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ ptr ] => + ltac:(M.monadic + (let ptr := M.alloc (| ptr |) in + M.call_closure (| + M.get_associated_function (| Ty.path "i16", "from_be_bytes", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + "try_into", + [] + |), + [ + M.call_closure (| + M.get_function (| "core::slice::raw::from_raw_parts", [ Ty.path "u8" ] |), + [ M.read (| ptr |); Value.Integer 2 ] + |) + ] + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_read_i16 : + M.IsFunction "revm_interpreter::instructions::utility::read_i16" read_i16. + + (* + pub(crate) unsafe fn read_u16(ptr: *const u8) -> u16 { + u16::from_be_bytes(core::slice::from_raw_parts(ptr, 2).try_into().unwrap()) + } + *) + Definition read_u16 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ ptr ] => + ltac:(M.monadic + (let ptr := M.alloc (| ptr |) in + M.call_closure (| + M.get_associated_function (| Ty.path "u16", "from_be_bytes", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + "try_into", + [] + |), + [ + M.call_closure (| + M.get_function (| "core::slice::raw::from_raw_parts", [ Ty.path "u8" ] |), + [ M.read (| ptr |); Value.Integer 2 ] + |) + ] + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_read_u16 : + M.IsFunction "revm_interpreter::instructions::utility::read_u16" read_u16. + End utility. +End instructions. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter.md new file mode 100644 index 00000000..62a8a3c6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter.md @@ -0,0 +1,3587 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter. + (* StructRecord + { + name := "Interpreter"; + ty_params := []; + fields := + [ + ("instruction_pointer", Ty.apply (Ty.path "*const") [ Ty.path "u8" ]); + ("gas", Ty.path "revm_interpreter::gas::Gas"); + ("contract", Ty.path "revm_interpreter::interpreter::contract::Contract"); + ("instruction_result", Ty.path "revm_interpreter::instruction_result::InstructionResult"); + ("bytecode", Ty.path "alloy_primitives::bytes_::Bytes"); + ("is_eof", Ty.path "bool"); + ("is_eof_init", Ty.path "bool"); + ("shared_memory", Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory"); + ("stack", Ty.path "revm_interpreter::interpreter::stack::Stack"); + ("function_stack", Ty.path "revm_interpreter::function_stack::FunctionStack"); + ("return_data_buffer", Ty.path "alloy_primitives::bytes_::Bytes"); + ("is_static", Ty.path "bool"); + ("next_action", Ty.path "revm_interpreter::interpreter_action::InterpreterAction") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_Interpreter. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::Interpreter". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "instruction_pointer" |); + M.read (| Value.String "gas" |); + M.read (| Value.String "contract" |); + M.read (| Value.String "instruction_result" |); + M.read (| Value.String "bytecode" |); + M.read (| Value.String "is_eof" |); + M.read (| Value.String "is_eof_init" |); + M.read (| Value.String "shared_memory" |); + M.read (| Value.String "stack" |); + M.read (| Value.String "function_stack" |); + M.read (| Value.String "return_data_buffer" |); + M.read (| Value.String "is_static" |); + M.read (| Value.String "next_action" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "bytecode" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "is_eof" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "is_eof_init" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "function_stack" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "is_static" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Interpreter" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_Interpreter. + + Module Impl_core_default_Default_for_revm_interpreter_interpreter_Interpreter. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::Interpreter". + + (* + fn default() -> Self { + Self::new(Contract::default(), 0, false) + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "new", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_interpreter::interpreter::contract::Contract", + [], + "default", + [] + |), + [] + |); + Value.Integer 0; + Value.Bool false + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_interpreter_Interpreter. + + (* StructRecord + { + name := "InterpreterResult"; + ty_params := []; + fields := + [ + ("result", Ty.path "revm_interpreter::instruction_result::InstructionResult"); + ("output", Ty.path "alloy_primitives::bytes_::Bytes"); + ("gas", Ty.path "revm_interpreter::gas::Gas") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_InterpreterResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::InterpreterResult". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::interpreter::InterpreterResult" + [ + ("result", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_interpreter::instruction_result::InstructionResult", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + ] + |)); + ("output", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |)); + ("gas", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_interpreter::gas::Gas", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_InterpreterResult. + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_InterpreterResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::InterpreterResult". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "InterpreterResult" |); + M.read (| Value.String "result" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |)); + M.read (| Value.String "output" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |)); + M.read (| Value.String "gas" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_InterpreterResult. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_InterpreterResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::InterpreterResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_InterpreterResult. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_InterpreterResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::InterpreterResult". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::instruction_result::InstructionResult", + [ Ty.path "revm_interpreter::instruction_result::InstructionResult" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::gas::Gas", + [ Ty.path "revm_interpreter::gas::Gas" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_InterpreterResult. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_InterpreterResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::InterpreterResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_InterpreterResult. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_InterpreterResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::InterpreterResult". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_InterpreterResult. + + Module Impl_revm_interpreter_interpreter_Interpreter. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::Interpreter". + + (* + pub fn new(contract: Contract, gas_limit: u64, is_static: bool) -> Self { + if !contract.bytecode.is_execution_ready() { + panic!("Contract is not execution ready {:?}", contract.bytecode); + } + let is_eof = contract.bytecode.is_eof(); + let bytecode = contract.bytecode.bytecode().clone(); + Self { + instruction_pointer: bytecode.as_ptr(), + bytecode, + contract, + gas: Gas::new(gas_limit), + instruction_result: InstructionResult::Continue, + function_stack: FunctionStack::default(), + is_static, + is_eof, + is_eof_init: false, + return_data_buffer: Bytes::new(), + shared_memory: EMPTY_SHARED_MEMORY, + stack: Stack::new(), + next_action: InterpreterAction::None, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ contract; gas_limit; is_static ] => + ltac:(M.monadic + (let contract := M.alloc (| contract |) in + let gas_limit := M.alloc (| gas_limit |) in + let is_static := M.alloc (| is_static |) in + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "is_execution_ready", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + contract, + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "Contract is not execution ready " + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "revm_primitives::bytecode::Bytecode" ] + |), + [ + M.SubPointer.get_struct_record_field (| + contract, + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ is_eof := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "is_eof", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + contract, + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |) + |) in + let~ bytecode := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "bytecode", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + contract, + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm_interpreter::interpreter::Interpreter" + [ + ("instruction_pointer", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ bytecode ] + |) + ] + |) + ] + |)); + ("bytecode", M.read (| bytecode |)); + ("contract", M.read (| contract |)); + ("gas", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "new", + [] + |), + [ M.read (| gas_limit |) ] + |)); + ("instruction_result", + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Continue" + []); + ("function_stack", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_interpreter::function_stack::FunctionStack", + [], + "default", + [] + |), + [] + |)); + ("is_static", M.read (| is_static |)); + ("is_eof", M.read (| is_eof |)); + ("is_eof_init", Value.Bool false); + ("return_data_buffer", + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |)); + ("shared_memory", + M.read (| + M.get_constant (| + "revm_interpreter::interpreter::shared_memory::EMPTY_SHARED_MEMORY" + |) + |)); + ("stack", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "new", + [] + |), + [] + |)); + ("next_action", + Value.StructTuple + "revm_interpreter::interpreter_action::InterpreterAction::None" + []) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn set_is_eof_init(&mut self) { + self.is_eof_init = true; + } + *) + Definition set_is_eof_init (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "is_eof_init" + |), + Value.Bool true + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_is_eof_init : + M.IsAssociatedFunction Self "set_is_eof_init" set_is_eof_init. + + (* + pub fn eof(&self) -> Option<&Eof> { + self.contract.bytecode.eof() + } + *) + Definition eof (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "eof", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_eof : M.IsAssociatedFunction Self "eof" eof. + + (* + pub(crate) fn load_eof_code(&mut self, idx: usize, pc: usize) { + // SAFETY: eof flag is true only if bytecode is Eof. + let Bytecode::Eof(eof) = &self.contract.bytecode else { + panic!("Expected EOF bytecode") + }; + let Some(code) = eof.body.code(idx) else { + panic!("Code not found") + }; + self.bytecode = code.clone(); + self.instruction_pointer = unsafe { self.bytecode.as_ptr().add(pc) }; + } + *) + Definition load_eof_code (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; idx; pc ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let idx := M.alloc (| idx |) in + let pc := M.alloc (| pc |) in + M.read (| + M.match_operator (| + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let eof := M.alloc (| ฮณ1_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + "code", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |); + M.read (| idx |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let code := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "bytecode" + |), + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ M.read (| code |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "bytecode" + |) + ] + |) + ] + |) + ] + |); + M.read (| pc |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_eof_code : + M.IsAssociatedFunction Self "load_eof_code" load_eof_code. + + (* + pub fn insert_create_outcome(&mut self, create_outcome: CreateOutcome) { + self.instruction_result = InstructionResult::Continue; + + let instruction_result = create_outcome.instruction_result(); + self.return_data_buffer = if instruction_result.is_revert() { + // Save data to return data buffer if the create reverted + create_outcome.output().to_owned() + } else { + // Otherwise clear it + Bytes::new() + }; + + match instruction_result { + return_ok!() => { + let address = create_outcome.address; + push_b256!(self, address.unwrap_or_default().into_word()); + self.gas.erase_cost(create_outcome.gas().remaining()); + self.gas.record_refund(create_outcome.gas().refunded()); + } + return_revert!() => { + push!(self, U256::ZERO); + self.gas.erase_cost(create_outcome.gas().remaining()); + } + InstructionResult::FatalExternalError => { + panic!("Fatal external error in insert_create_outcome"); + } + _ => { + push!(self, U256::ZERO); + } + } + } + *) + Definition insert_create_outcome (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; create_outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let create_outcome := M.alloc (| create_outcome |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Continue" + [] + |) in + let~ instruction_result := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "instruction_result", + [] + |), + [ create_outcome ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |), + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::instruction_result::InstructionResult", + "is_revert", + [] + |), + [ M.read (| M.read (| instruction_result |) |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "alloc::borrow::ToOwned", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "to_owned", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "output", + [] + |), + [ create_outcome ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |) + |))) + ] + |) + |) + |) in + M.match_operator (| + instruction_result, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Continue" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Stop" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Return" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ address := + M.copy (| + M.SubPointer.get_struct_record_field (| + create_outcome, + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "address" + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_b256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "into_word", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "alloy_primitives::bits::address::Address" + ], + "unwrap_or_default", + [] + |), + [ M.read (| address |) ] + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "erase_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "gas", + [] + |), + [ create_outcome ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_refund", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "gas", + [] + |), + [ create_outcome ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Revert" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| M.get_constant (| "ruint::ZERO" |) |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "erase_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "gas", + [] + |), + [ create_outcome ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::FatalExternalError" + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "Fatal external error in insert_create_outcome" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| M.get_constant (| "ruint::ZERO" |) |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_create_outcome : + M.IsAssociatedFunction Self "insert_create_outcome" insert_create_outcome. + + (* + pub fn insert_eofcreate_outcome(&mut self, create_outcome: EOFCreateOutcome) { + let instruction_result = create_outcome.instruction_result(); + + self.return_data_buffer = if *instruction_result == InstructionResult::Revert { + // Save data to return data buffer if the create reverted + create_outcome.output().to_owned() + } else { + // Otherwise clear it. Note that RETURN opcode should abort. + Bytes::new() + }; + + match instruction_result { + InstructionResult::ReturnContract => { + push_b256!(self, create_outcome.address.into_word()); + self.gas.erase_cost(create_outcome.gas().remaining()); + self.gas.record_refund(create_outcome.gas().refunded()); + } + return_revert!() => { + push!(self, U256::ZERO); + self.gas.erase_cost(create_outcome.gas().remaining()); + } + InstructionResult::FatalExternalError => { + panic!("Fatal external error in insert_eofcreate_outcome"); + } + _ => { + push!(self, U256::ZERO); + } + } + } + *) + Definition insert_eofcreate_outcome (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; create_outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let create_outcome := M.alloc (| create_outcome |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ instruction_result := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "instruction_result", + [] + |), + [ create_outcome ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |), + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "revm_interpreter::instruction_result::InstructionResult", + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ], + "eq", + [] + |), + [ + M.read (| instruction_result |); + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Revert" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "alloc::borrow::ToOwned", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "to_owned", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "output", + [] + |), + [ create_outcome ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |) + |))) + ] + |) + |) + |) in + M.match_operator (| + instruction_result, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push_b256", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "into_word", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + create_outcome, + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "address" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "erase_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "gas", + [] + |), + [ create_outcome ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_refund", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "gas", + [] + |), + [ create_outcome ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Revert" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| M.get_constant (| "ruint::ZERO" |) |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "erase_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "gas", + [] + |), + [ create_outcome ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::FatalExternalError" + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "Fatal external error in insert_eofcreate_outcome" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| M.get_constant (| "ruint::ZERO" |) |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_eofcreate_outcome : + M.IsAssociatedFunction Self "insert_eofcreate_outcome" insert_eofcreate_outcome. + + (* + pub fn insert_call_outcome( + &mut self, + shared_memory: &mut SharedMemory, + call_outcome: CallOutcome, + ) { + self.instruction_result = InstructionResult::Continue; + self.return_data_buffer.clone_from(call_outcome.output()); + + let out_offset = call_outcome.memory_start(); + let out_len = call_outcome.memory_length(); + + let target_len = min(out_len, self.return_data_buffer.len()); + match call_outcome.instruction_result() { + return_ok!() => { + // return unspend gas. + let remaining = call_outcome.gas().remaining(); + let refunded = call_outcome.gas().refunded(); + self.gas.erase_cost(remaining); + self.gas.record_refund(refunded); + shared_memory.set(out_offset, &self.return_data_buffer[..target_len]); + push!(self, U256::from(1)); + } + return_revert!() => { + self.gas.erase_cost(call_outcome.gas().remaining()); + shared_memory.set(out_offset, &self.return_data_buffer[..target_len]); + push!(self, U256::ZERO); + } + InstructionResult::FatalExternalError => { + panic!("Fatal external error in insert_call_outcome"); + } + _ => { + push!(self, U256::ZERO); + } + } + } + *) + Definition insert_call_outcome (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; shared_memory; call_outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let shared_memory := M.alloc (| shared_memory |) in + let call_outcome := M.alloc (| call_outcome |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Continue" + [] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone_from", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "output", + [] + |), + [ call_outcome ] + |) + ] + |) + |) in + let~ out_offset := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "memory_start", + [] + |), + [ call_outcome ] + |) + |) in + let~ out_len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "memory_length", + [] + |), + [ call_outcome ] + |) + |) in + let~ target_len := + M.alloc (| + M.call_closure (| + M.get_function (| "core::cmp::min", [ Ty.path "usize" ] |), + [ + M.read (| out_len |); + M.call_closure (| + M.get_associated_function (| Ty.path "bytes::bytes::Bytes", "len", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |) + ] + |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "instruction_result", + [] + |), + [ call_outcome ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Continue" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Stop" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Return" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ remaining := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "gas", + [] + |), + [ call_outcome ] + |) + |) + ] + |) + |) in + let~ refunded := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "gas", + [] + |), + [ call_outcome ] + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "erase_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| remaining |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_refund", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| refunded |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set", + [] + |), + [ + M.read (| shared_memory |); + M.read (| out_offset |); + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |) + ] + |) + ] + |); + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", M.read (| target_len |)) ] + ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 1 ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Revert" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "erase_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "gas", + [] + |), + [ call_outcome ] + |) + |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set", + [] + |), + [ + M.read (| shared_memory |); + M.read (| out_offset |); + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "return_data_buffer" + |) + ] + |) + ] + |); + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", M.read (| target_len |)) ] + ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| M.get_constant (| "ruint::ZERO" |) |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::FatalExternalError" + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "Fatal external error in insert_call_outcome" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |); + M.read (| M.get_constant (| "ruint::ZERO" |) |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |), + M.read (| e |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_call_outcome : + M.IsAssociatedFunction Self "insert_call_outcome" insert_call_outcome. + + (* + pub fn current_opcode(&self) -> u8 { + unsafe { *self.instruction_pointer } + } + *) + Definition current_opcode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_current_opcode : + M.IsAssociatedFunction Self "current_opcode" current_opcode. + + (* + pub fn contract(&self) -> &Contract { + &self.contract + } + *) + Definition contract (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "contract" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_contract : M.IsAssociatedFunction Self "contract" contract. + + (* + pub fn gas(&self) -> &Gas { + &self.gas + } + *) + Definition gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_gas : M.IsAssociatedFunction Self "gas" gas. + + (* + pub fn stack(&self) -> &Stack { + &self.stack + } + *) + Definition stack (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_stack : M.IsAssociatedFunction Self "stack" stack. + + (* + pub fn program_counter(&self) -> usize { + // SAFETY: `instruction_pointer` should be at an offset from the start of the bytecode. + // In practice this is always true unless a caller modifies the `instruction_pointer` field manually. + unsafe { self.instruction_pointer.offset_from(self.bytecode.as_ptr()) as usize } + } + *) + Definition program_counter (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset_from", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "bytecode" + |) + ] + |) + ] + |) + ] + |) + ] + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_program_counter : + M.IsAssociatedFunction Self "program_counter" program_counter. + + (* + pub(crate) fn step(&mut self, instruction_table: &[FN; 256], host: &mut H) + where + FN: Fn(&mut Interpreter, &mut H), + { + // Get current opcode. + let opcode = unsafe { *self.instruction_pointer }; + + // SAFETY: In analysis we are doing padding of bytecode so that we are sure that last + // byte instruction is STOP so we are safe to just increment program_counter bcs on last instruction + // it will do noop and just stop execution of this contract + self.instruction_pointer = unsafe { self.instruction_pointer.offset(1) }; + + // execute instruction. + (instruction_table[opcode as usize])(self, host) + } + *) + Definition step (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ FN; H ], [ self; instruction_table; host ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let instruction_table := M.alloc (| instruction_table |) in + let host := M.alloc (| host |) in + M.read (| + let~ opcode := + M.copy (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + Value.Integer 1 + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + FN, + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::Interpreter" ]; + Ty.apply (Ty.path "&mut") [ H ] + ] + ], + "call", + [] + |), + [ + M.SubPointer.get_array_field (| + M.read (| instruction_table |), + M.alloc (| M.rust_cast (M.read (| opcode |)) |) + |); + Value.Tuple [ M.read (| self |); M.read (| host |) ] + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_step : M.IsAssociatedFunction Self "step" step. + + (* + pub fn take_memory(&mut self) -> SharedMemory { + core::mem::replace(&mut self.shared_memory, EMPTY_SHARED_MEMORY) + } + *) + Definition take_memory (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_function (| + "core::mem::replace", + [ Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.read (| + M.get_constant (| + "revm_interpreter::interpreter::shared_memory::EMPTY_SHARED_MEMORY" + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_take_memory : M.IsAssociatedFunction Self "take_memory" take_memory. + + (* + pub fn run( + &mut self, + shared_memory: SharedMemory, + instruction_table: &[FN; 256], + host: &mut H, + ) -> InterpreterAction + where + FN: Fn(&mut Interpreter, &mut H), + { + self.next_action = InterpreterAction::None; + self.shared_memory = shared_memory; + // main loop + while self.instruction_result == InstructionResult::Continue { + self.step(instruction_table, host); + } + + // Return next action if it is some. + if self.next_action.is_some() { + return core::mem::take(&mut self.next_action); + } + // If not, return action without output as it is a halt. + InterpreterAction::Return { + result: InterpreterResult { + result: self.instruction_result, + // return empty bytecode + output: Bytes::new(), + gas: self.gas, + }, + } + } + *) + Definition run (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ FN; H ], [ self; shared_memory; instruction_table; host ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let shared_memory := M.alloc (| shared_memory |) in + let instruction_table := M.alloc (| instruction_table |) in + let host := M.alloc (| host |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |), + Value.StructTuple + "revm_interpreter::interpreter_action::InterpreterAction::None" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |), + M.read (| shared_memory |) + |) in + let~ _ := + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "revm_interpreter::instruction_result::InstructionResult", + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |); + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Continue" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "step", + [ FN; H ] + |), + [ + M.read (| self |); + M.read (| instruction_table |); + M.read (| host |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::InterpreterAction", + "is_some", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_function (| + "core::mem::take", + [ + Ty.path + "revm_interpreter::interpreter_action::InterpreterAction" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "next_action" + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Return" + [ + ("result", + Value.StructRecord + "revm_interpreter::interpreter::InterpreterResult" + [ + ("result", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |) + |)); + ("output", + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |)); + ("gas", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + |)) + ]) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_run : M.IsAssociatedFunction Self "run" run. + + (* + pub fn resize_memory(&mut self, new_size: usize) -> bool { + resize_memory(&mut self.shared_memory, &mut self.gas, new_size) + } + *) + Definition resize_memory (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; new_size ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let new_size := M.alloc (| new_size |) in + M.call_closure (| + M.get_function (| "revm_interpreter::interpreter::resize_memory", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |); + M.read (| new_size |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_resize_memory : + M.IsAssociatedFunction Self "resize_memory" resize_memory. + End Impl_revm_interpreter_interpreter_Interpreter. + + Module Impl_revm_interpreter_interpreter_InterpreterResult. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::InterpreterResult". + + (* + pub const fn is_ok(&self) -> bool { + self.result.is_ok() + } + *) + Definition is_ok (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::instruction_result::InstructionResult", + "is_ok", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_ok : M.IsAssociatedFunction Self "is_ok" is_ok. + + (* + pub const fn is_revert(&self) -> bool { + self.result.is_revert() + } + *) + Definition is_revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::instruction_result::InstructionResult", + "is_revert", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_revert : M.IsAssociatedFunction Self "is_revert" is_revert. + + (* + pub const fn is_error(&self) -> bool { + self.result.is_error() + } + *) + Definition is_error (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::instruction_result::InstructionResult", + "is_error", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_error : M.IsAssociatedFunction Self "is_error" is_error. + End Impl_revm_interpreter_interpreter_InterpreterResult. + + (* + pub fn resize_memory(memory: &mut SharedMemory, gas: &mut Gas, new_size: usize) -> bool { + let new_words = num_words(new_size as u64); + let new_cost = gas::memory_gas(new_words); + let current_cost = memory.current_expansion_cost(); + let cost = new_cost - current_cost; + let success = gas.record_cost(cost); + if success { + memory.resize((new_words as usize) * 32); + } + success + } + *) + Definition resize_memory (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ memory; gas; new_size ] => + ltac:(M.monadic + (let memory := M.alloc (| memory |) in + let gas := M.alloc (| gas |) in + let new_size := M.alloc (| new_size |) in + M.read (| + let~ new_words := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::interpreter::shared_memory::num_words", [] |), + [ M.rust_cast (M.read (| new_size |)) ] + |) + |) in + let~ new_cost := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::memory_gas", [] |), + [ M.read (| new_words |) ] + |) + |) in + let~ current_cost := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "current_expansion_cost", + [] + |), + [ M.read (| memory |) ] + |) + |) in + let~ cost := + M.alloc (| + BinOp.Wrap.sub Integer.U64 (M.read (| new_cost |)) (M.read (| current_cost |)) + |) in + let~ success := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ M.read (| gas |); M.read (| cost |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use success in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "resize", + [] + |), + [ + M.read (| memory |); + BinOp.Wrap.mul + Integer.Usize + (M.rust_cast (M.read (| new_words |))) + (Value.Integer 32) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + success + |))) + | _, _ => M.impossible + end. + + Axiom Function_resize_memory : + M.IsFunction "revm_interpreter::interpreter::resize_memory" resize_memory. +End interpreter. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/analysis.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/analysis.md new file mode 100644 index 00000000..ed88800a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/analysis.md @@ -0,0 +1,7004 @@ +# ๐Ÿ“ analysis.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter/analysis.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter. + Module analysis. + Definition value_EOF_NON_RETURNING_FUNCTION : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 128 |))). + + (* + pub fn to_analysed(bytecode: Bytecode) -> Bytecode { + let (bytes, len) = match bytecode { + Bytecode::LegacyRaw(bytecode) => { + let len = bytecode.len(); + let mut padded_bytecode = Vec::with_capacity(len + 33); + padded_bytecode.extend_from_slice(&bytecode); + padded_bytecode.resize(len + 33, 0); + (Bytes::from(padded_bytecode), len) + } + n => return n, + }; + let jump_table = analyze(bytes.as_ref()); + + Bytecode::LegacyAnalyzed(LegacyAnalyzedBytecode::new(bytes, len, jump_table)) + } + *) + Definition to_analysed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ bytecode ] => + ltac:(M.monadic + (let bytecode := M.alloc (| bytecode |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.match_operator (| + bytecode, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let bytecode := M.copy (| ฮณ0_0 |) in + let~ len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ bytecode ] + |) + ] + |) + |) in + let~ padded_bytecode := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "with_capacity", + [] + |), + [ BinOp.Wrap.add Integer.Usize (M.read (| len |)) (Value.Integer 33) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "extend_from_slice", + [] + |), + [ + padded_bytecode; + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ bytecode ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "resize", + [] + |), + [ + padded_bytecode; + BinOp.Wrap.add + Integer.Usize + (M.read (| len |)) + (Value.Integer 33); + Value.Integer 0 + ] + |) + |) in + M.alloc (| + Value.Tuple + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "alloy_primitives::bytes_::Bytes", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ] + ], + "from", + [] + |), + [ M.read (| padded_bytecode |) ] + |); + M.read (| len |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let n := M.copy (| ฮณ |) in + M.alloc (| + M.never_to_any (| M.read (| M.return_ (| M.read (| n |) |) |) |) + |))) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let bytes := M.copy (| ฮณ0_0 |) in + let len := M.copy (| ฮณ0_1 |) in + let~ jump_table := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::analysis::analyze", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::AsRef", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + "as_ref", + [] + |), + [ bytes ] + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "new", + [] + |), + [ M.read (| bytes |); M.read (| len |); M.read (| jump_table |) ] + |) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_to_analysed : + M.IsFunction "revm_interpreter::interpreter::analysis::to_analysed" to_analysed. + + (* + fn analyze(code: &[u8]) -> JumpTable { + let mut jumps: BitVec = bitvec![u8, Lsb0; 0; code.len()]; + + let range = code.as_ptr_range(); + let start = range.start; + let mut iterator = start; + let end = range.end; + while iterator < end { + let opcode = unsafe { *iterator }; + if opcode::JUMPDEST == opcode { + // SAFETY: jumps are max length of the code + unsafe { jumps.set_unchecked(iterator.offset_from(start) as usize, true) } + iterator = unsafe { iterator.offset(1) }; + } else { + let push_offset = opcode.wrapping_sub(opcode::PUSH1); + if push_offset < 32 { + // SAFETY: iterator access range is checked in the while loop + iterator = unsafe { iterator.offset((push_offset + 2) as isize) }; + } else { + // SAFETY: iterator access range is checked in the while loop + iterator = unsafe { iterator.offset(1) }; + } + } + } + + JumpTable(Arc::new(jumps)) + } + *) + Definition analyze (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ code ] => + ltac:(M.monadic + (let code := M.alloc (| code |) in + M.read (| + let~ jumps := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ], + "repeat", + [] + |), + [ + BinOp.Pure.ne (Value.Integer 0) (Value.Integer 0); + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| code |) ] + |) + ] + |) + |) in + let~ range := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr_range", + [] + |), + [ M.read (| code |) ] + |) + |) in + let~ start := + M.copy (| + M.SubPointer.get_struct_record_field (| range, "core::ops::range::Range", "start" |) + |) in + let~ iterator := M.copy (| start |) in + let~ end_ := + M.copy (| + M.SubPointer.get_struct_record_field (| range, "core::ops::range::Range", "end" |) + |) in + let~ _ := + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt (M.read (| iterator |)) (M.read (| end_ |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ opcode := M.copy (| M.read (| iterator |) |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| + M.get_constant (| + "revm_interpreter::opcode::JUMPDEST" + |) + |)) + (M.read (| opcode |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "bitvec::slice::BitSlice") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ], + "set_unchecked", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ], + [], + "deref_mut", + [] + |), + [ jumps ] + |); + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset_from", + [] + |), + [ M.read (| iterator |); M.read (| start |) ] + |)); + Value.Bool true + ] + |) + |) in + let~ _ := + M.write (| + iterator, + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ M.read (| iterator |); Value.Integer 1 ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ push_offset := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "u8", + "wrapping_sub", + [] + |), + [ + M.read (| opcode |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::PUSH1" |) + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.read (| push_offset |)) + (Value.Integer 32) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + iterator, + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ + M.read (| iterator |); + M.rust_cast + (BinOp.Wrap.add + Integer.U8 + (M.read (| push_offset |)) + (Value.Integer 2)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.write (| + iterator, + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "offset", + [] + |), + [ M.read (| iterator |); Value.Integer 1 ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| M.never_to_any (| M.read (| M.break (||) |) |) |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::bytecode::legacy::jump_map::JumpTable" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| jumps |) ] + |) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_analyze : + M.IsFunction "revm_interpreter::interpreter::analysis::analyze" analyze. + + (* + pub fn validate_raw_eof(bytecode: Bytes) -> Result { + let eof = Eof::decode(bytecode)?; + validate_eof(&eof)?; + Ok(eof) + } + *) + Definition validate_raw_eof (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ bytecode ] => + ltac:(M.monadic + (let bytecode := M.alloc (| bytecode |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ eof := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::eof::Eof"; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "decode", + [] + |), + [ M.read (| bytecode |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::eof::Eof"; + Ty.path + "revm_interpreter::interpreter::analysis::EofError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path "revm_interpreter::interpreter::analysis::EofError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::analysis::validate_eof", + [] + |), + [ eof ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::eof::Eof"; + Ty.path + "revm_interpreter::interpreter::analysis::EofError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_interpreter::interpreter::analysis::EofError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ M.read (| eof |) ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_validate_raw_eof : + M.IsFunction "revm_interpreter::interpreter::analysis::validate_raw_eof" validate_raw_eof. + + (* + pub fn validate_eof(eof: &Eof) -> Result<(), EofError> { + // clone is cheap as it is Bytes and a header. + let mut queue = vec![eof.clone()]; + + while let Some(eof) = queue.pop() { + // iterate over types + validate_eof_codes(&eof)?; + // iterate over containers, convert them to Eof and add to analyze_eof + for container in eof.body.container_section { + queue.push(Eof::decode(container)?); + } + } + + // Eof is valid + Ok(()) + } + *) + Definition validate_eof (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ eof ] => + ltac:(M.monadic + (let eof := M.alloc (| eof |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ queue := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "revm_primitives::bytecode::eof::Eof" ], + "into_vec", + [ Ty.path "alloc::alloc::Global" ] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.apply + (Ty.path "array") + [ Ty.path "revm_primitives::bytecode::eof::Eof" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::eof::Eof", + [], + "clone", + [] + |), + [ M.read (| eof |) ] + |) + ] + |) + ] + |) + |)) + ] + |) + |) in + let~ _ := + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_primitives::bytecode::eof::Eof"; + Ty.path "alloc::alloc::Global" + ], + "pop", + [] + |), + [ queue ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let eof := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::analysis::validate_eof_codes", + [] + |), + [ eof ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_interpreter::interpreter::analysis::EofError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + eof, + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.break (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let container := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_primitives::bytecode::eof::Eof"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + queue; + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm_primitives::bytecode::eof::Eof"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::bytecode::eof::Eof", + "decode", + [] + |), + [ M.read (| container |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := + M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_interpreter::interpreter::analysis::EofError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_validate_eof : + M.IsFunction "revm_interpreter::interpreter::analysis::validate_eof" validate_eof. + + (* + pub fn validate_eof_codes(eof: &Eof) -> Result<(), EofValidationError> { + let mut queued_codes = vec![false; eof.body.code_section.len()]; + if eof.body.code_section.len() != eof.body.types_section.len() { + return Err(EofValidationError::InvalidTypesSection); + } + + if eof.body.code_section.is_empty() { + // no code sections. This should be already checked in decode. + return Err(EofValidationError::NoCodeSections); + } + // first section is default one. + queued_codes[0] = true; + + // the first code section must have a type signature + // (0, 0x80, max_stack_height) (0 inputs non-returning function) + let first_types = &eof.body.types_section[0]; + if first_types.inputs != 0 || first_types.outputs != EOF_NON_RETURNING_FUNCTION { + return Err(EofValidationError::InvalidTypesSection); + } + + // start validation from code section 0. + let mut queue = vec![0]; + while let Some(index) = queue.pop() { + let code = &eof.body.code_section[index]; + let accessed_codes = validate_eof_code( + code, + eof.header.data_size as usize, + index, + eof.body.container_section.len(), + &eof.body.types_section, + )?; + + // queue accessed codes. + accessed_codes.into_iter().for_each(|i| { + if !queued_codes[i] { + queued_codes[i] = true; + queue.push(i); + } + }); + } + // iterate over accessed codes and check if all are accessed. + if queued_codes.into_iter().any(|x| !x) { + return Err(EofValidationError::CodeSectionNotAccessed); + } + + Ok(()) + } + *) + Definition validate_eof_codes (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ eof ] => + ltac:(M.monadic + (let eof := M.alloc (| eof |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ queued_codes := + M.alloc (| + M.call_closure (| + M.get_function (| "alloc::vec::from_elem", [ Ty.path "bool" ] |), + [ + Value.Bool false; + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |) + ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |) + ] + |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::InvalidTypesSection" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::NoCodeSections" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "bool"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "usize" ], + "index_mut", + [] + |), + [ queued_codes; Value.Integer 0 ] + |), + Value.Bool true + |) in + let~ first_types := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ], + [ Ty.path "usize" ], + "index", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |); + Value.Integer 0 + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| first_types |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| first_types |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |)) + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::analysis::EOF_NON_RETURNING_FUNCTION" + |) + |)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::InvalidTypesSection" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ queue := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "usize" ], + "into_vec", + [ Ty.path "alloc::alloc::Global" ] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.apply (Ty.path "array") [ Ty.path "usize" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.alloc (| Value.Array [ Value.Integer 0 ] |) ] + |) + |)) + ] + |) + |) in + let~ _ := + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ], + "pop", + [] + |), + [ queue ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let index := M.copy (| ฮณ0_0 |) in + let~ code := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [ Ty.path "usize" ], + "index", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |); + M.read (| index |) + ] + |) + |) in + let~ accessed_codes := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "usize"; + Ty.path "std::hash::random::RandomState" + ]; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::analysis::validate_eof_code", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| code |) ] + |) + ] + |); + M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "header" + |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + |)); + M.read (| index |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |) + ] + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::set::IntoIter") + [ Ty.path "usize" ], + [], + "for_each", + [ Ty.function [ Ty.tuple [ Ty.path "usize" ] ] (Ty.tuple []) ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "usize"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ M.read (| accessed_codes |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let i := M.copy (| ฮณ |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path "bool"; + Ty.path + "alloc::alloc::Global" + ], + [ Ty.path "usize" ], + "index", + [] + |), + [ + queued_codes; + M.read (| i |) + ] + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path "bool"; + Ty.path + "alloc::alloc::Global" + ], + [ Ty.path "usize" ], + "index_mut", + [] + |), + [ queued_codes; M.read (| i |) + ] + |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path "usize"; + Ty.path + "alloc::alloc::Global" + ], + "push", + [] + |), + [ queue; M.read (| i |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ Ty.path "bool"; Ty.path "alloc::alloc::Global" ], + [], + "any", + [ Ty.function [ Ty.tuple [ Ty.path "bool" ] ] (Ty.path "bool") ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "bool"; Ty.path "alloc::alloc::Global" ], + [], + "into_iter", + [] + |), + [ M.read (| queued_codes |) ] + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let x := M.copy (| ฮณ |) in + UnOp.Pure.not (M.read (| x |)))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::CodeSectionNotAccessed" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_validate_eof_codes : + M.IsFunction "revm_interpreter::interpreter::analysis::validate_eof_codes" validate_eof_codes. + + (* + Enum EofError + { + ty_params := []; + variants := + [ + { + name := "Decode"; + item := StructTuple [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ]; + discriminant := None; + }; + { + name := "Validation"; + item := + StructTuple [ Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofError::Decode", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Decode" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofError::Validation", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Validation" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_hash_Hash_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "isize", + [], + "hash", + [ __H ] + |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofError::Decode", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::bytecode::eof::EofDecodeError", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofError::Validation", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::interpreter::analysis::EofError::Decode", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::interpreter::analysis::EofError::Decode", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::bytecode::eof::EofDecodeError", + [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::interpreter::analysis::EofError::Validation", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::interpreter::analysis::EofError::Validation", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError", + [ + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::intrinsics::unreachable", [] |), + [] + |) + |) + |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_cmp_PartialOrd_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::interpreter::analysis::EofError::Decode", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::interpreter::analysis::EofError::Decode", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "revm_primitives::bytecode::eof::EofDecodeError", + [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ], + "partial_cmp", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::interpreter::analysis::EofError::Validation", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::interpreter::analysis::EofError::Validation", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError", + [ Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" + ], + "partial_cmp", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "isize", + [ Ty.path "isize" ], + "partial_cmp", + [] + |), + [ __self_tag; __arg1_tag ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_cmp_Ord_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "isize", [], "cmp", [] |), + [ __self_tag; __arg1_tag ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::cmp::Ordering::Equal" |) in + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::interpreter::analysis::EofError::Decode", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::interpreter::analysis::EofError::Decode", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "revm_primitives::bytecode::eof::EofDecodeError", + [], + "cmp", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::interpreter::analysis::EofError::Validation", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::interpreter::analysis::EofError::Validation", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError", + [], + "cmp", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::intrinsics::unreachable", [] |), + [] + |) + |) + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_marker_Copy_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_convert_From_revm_primitives_bytecode_eof_EofDecodeError_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + (* + fn from(err: EofDecodeError) -> Self { + EofError::Decode(err) + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ err ] => + ltac:(M.monadic + (let err := M.alloc (| err |) in + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofError::Decode" + [ M.read (| err |) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ (* T *) Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_primitives_bytecode_eof_EofDecodeError_for_revm_interpreter_interpreter_analysis_EofError. + + Module Impl_core_convert_From_revm_interpreter_interpreter_analysis_EofValidationError_for_revm_interpreter_interpreter_analysis_EofError. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::analysis::EofError". + + (* + fn from(err: EofValidationError) -> Self { + EofError::Validation(err) + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ err ] => + ltac:(M.monadic + (let err := M.alloc (| err |) in + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofError::Validation" + [ M.read (| err |) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ (* T *) Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_interpreter_interpreter_analysis_EofValidationError_for_revm_interpreter_interpreter_analysis_EofError. + + (* + Enum EofValidationError + { + ty_params := []; + variants := + [ + { + name := "FalsePossitive"; + item := StructTuple []; + discriminant := None; + }; + { + name := "UnknownOpcode"; + item := StructTuple []; + discriminant := None; + }; + { + name := "OpcodeDisabled"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InstructionNotForwardAccessed"; + item := StructTuple []; + discriminant := None; + }; + { + name := "MissingImmediateBytes"; + item := StructTuple []; + discriminant := None; + }; + { + name := "MissingRJUMPVImmediateBytes"; + item := StructTuple []; + discriminant := None; + }; + { + name := "JumpToImmediateBytes"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BackwardJumpToImmediateBytes"; + item := StructTuple []; + discriminant := None; + }; + { + name := "RJUMPVZeroMaxIndex"; + item := StructTuple []; + discriminant := None; + }; + { + name := "JumpZeroOffset"; + item := StructTuple []; + discriminant := None; + }; + { + name := "EOFCREATEInvalidIndex"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CodeSectionOutOfBounds"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CALLFNonReturningFunction"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StackOverflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "JUMPFEnoughOutputs"; + item := StructTuple []; + discriminant := None; + }; + { + name := "JUMPFStackHigherThanOutputs"; + item := StructTuple []; + discriminant := None; + }; + { + name := "DataLoadOutOfBounds"; + item := StructTuple []; + discriminant := None; + }; + { + name := "RETFBiggestStackNumMoreThenOutputs"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StackUnderflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "TypesStackUnderflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "JumpUnderflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "JumpOverflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BackwardJumpBiggestNumMismatch"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BackwardJumpSmallestNumMismatch"; + item := StructTuple []; + discriminant := None; + }; + { + name := "LastInstructionNotTerminating"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CodeSectionNotAccessed"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidTypesSection"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidFirstTypesSection"; + item := StructTuple []; + discriminant := None; + }; + { + name := "MaxStackMismatch"; + item := StructTuple []; + discriminant := None; + }; + { + name := "NoCodeSections"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::FalsePossitive" + |) in + M.alloc (| M.read (| Value.String "FalsePossitive" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::UnknownOpcode" + |) in + M.alloc (| M.read (| Value.String "UnknownOpcode" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::OpcodeDisabled" + |) in + M.alloc (| M.read (| Value.String "OpcodeDisabled" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::InstructionNotForwardAccessed" + |) in + M.alloc (| M.read (| Value.String "InstructionNotForwardAccessed" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::MissingImmediateBytes" + |) in + M.alloc (| M.read (| Value.String "MissingImmediateBytes" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::MissingRJUMPVImmediateBytes" + |) in + M.alloc (| M.read (| Value.String "MissingRJUMPVImmediateBytes" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::JumpToImmediateBytes" + |) in + M.alloc (| M.read (| Value.String "JumpToImmediateBytes" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::BackwardJumpToImmediateBytes" + |) in + M.alloc (| M.read (| Value.String "BackwardJumpToImmediateBytes" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::RJUMPVZeroMaxIndex" + |) in + M.alloc (| M.read (| Value.String "RJUMPVZeroMaxIndex" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::JumpZeroOffset" + |) in + M.alloc (| M.read (| Value.String "JumpZeroOffset" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::EOFCREATEInvalidIndex" + |) in + M.alloc (| M.read (| Value.String "EOFCREATEInvalidIndex" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::CodeSectionOutOfBounds" + |) in + M.alloc (| M.read (| Value.String "CodeSectionOutOfBounds" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::CALLFNonReturningFunction" + |) in + M.alloc (| M.read (| Value.String "CALLFNonReturningFunction" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::StackOverflow" + |) in + M.alloc (| M.read (| Value.String "StackOverflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::JUMPFEnoughOutputs" + |) in + M.alloc (| M.read (| Value.String "JUMPFEnoughOutputs" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::JUMPFStackHigherThanOutputs" + |) in + M.alloc (| M.read (| Value.String "JUMPFStackHigherThanOutputs" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::DataLoadOutOfBounds" + |) in + M.alloc (| M.read (| Value.String "DataLoadOutOfBounds" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::RETFBiggestStackNumMoreThenOutputs" + |) in + M.alloc (| + M.read (| Value.String "RETFBiggestStackNumMoreThenOutputs" |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::StackUnderflow" + |) in + M.alloc (| M.read (| Value.String "StackUnderflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::TypesStackUnderflow" + |) in + M.alloc (| M.read (| Value.String "TypesStackUnderflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::JumpUnderflow" + |) in + M.alloc (| M.read (| Value.String "JumpUnderflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::JumpOverflow" + |) in + M.alloc (| M.read (| Value.String "JumpOverflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::BackwardJumpBiggestNumMismatch" + |) in + M.alloc (| + M.read (| Value.String "BackwardJumpBiggestNumMismatch" |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::BackwardJumpSmallestNumMismatch" + |) in + M.alloc (| + M.read (| Value.String "BackwardJumpSmallestNumMismatch" |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::LastInstructionNotTerminating" + |) in + M.alloc (| M.read (| Value.String "LastInstructionNotTerminating" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::CodeSectionNotAccessed" + |) in + M.alloc (| M.read (| Value.String "CodeSectionNotAccessed" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::InvalidTypesSection" + |) in + M.alloc (| M.read (| Value.String "InvalidTypesSection" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::InvalidFirstTypesSection" + |) in + M.alloc (| M.read (| Value.String "InvalidFirstTypesSection" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::MaxStackMismatch" + |) in + M.alloc (| M.read (| Value.String "MaxStackMismatch" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter::analysis::EofValidationError::NoCodeSections" + |) in + M.alloc (| M.read (| Value.String "NoCodeSections" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_analysis_EofValidationError. + + Module Impl_core_hash_Hash_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_interpreter_analysis_EofValidationError. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_analysis_EofValidationError. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_analysis_EofValidationError. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_analysis_EofValidationError. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_analysis_EofValidationError. + + Module Impl_core_cmp_PartialOrd_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "isize", + [ Ty.path "isize" ], + "partial_cmp", + [] + |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_interpreter_interpreter_analysis_EofValidationError. + + Module Impl_core_cmp_Ord_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter::analysis::EofValidationError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "isize", [], "cmp", [] |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_interpreter_interpreter_analysis_EofValidationError. + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_analysis_EofValidationError. + + Module Impl_core_marker_Copy_for_revm_interpreter_interpreter_analysis_EofValidationError. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::EofValidationError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_interpreter_analysis_EofValidationError. + + (* + pub fn validate_eof_code( + code: &[u8], + data_size: usize, + this_types_index: usize, + num_of_containers: usize, + types: &[TypesSection], + ) -> Result, EofValidationError> { + let mut accessed_codes = HashSet::::new(); + let this_types = &types[this_types_index]; + + #[derive(Debug, Copy, Clone)] + struct InstructionInfo { + /// Is immediate byte, jumps can't happen on this part of code. + is_immediate: bool, + /// Have forward jump to this opcode. Used to check if opcode + /// after termination is accessed. + is_jumpdest: bool, + /// Smallest number of stack items accessed by jumps or sequential opcodes. + smallest: i32, + /// Biggest number of stack items accessed by jumps or sequential opcodes. + biggest: i32, + } + + impl InstructionInfo { + #[inline] + fn mark_as_immediate(&mut self) -> Result<(), EofValidationError> { + if self.is_jumpdest { + // Jump to immediate bytes. + return Err(EofValidationError::JumpToImmediateBytes); + } + self.is_immediate = true; + Ok(()) + } + } + + impl Default for InstructionInfo { + fn default() -> Self { + Self { + is_immediate: false, + is_jumpdest: false, + smallest: i32::MAX, + biggest: i32::MIN, + } + } + } + + // all bytes that are intermediate. + let mut jumps = vec![InstructionInfo::default(); code.len()]; + let mut is_after_termination = false; + + let mut next_smallest = this_types.inputs as i32; + let mut next_biggest = this_types.inputs as i32; + + let mut i = 0; + // We can check validity and jump destinations in one pass. + while i < code.len() { + let op = code[i]; + let opcode = &OPCODE_INFO_JUMPTABLE[op as usize]; + + let Some(opcode) = opcode else { + // err unknown opcode. + return Err(EofValidationError::UnknownOpcode); + }; + + if opcode.is_disabled_in_eof() { + // Opcode is disabled in EOF + return Err(EofValidationError::OpcodeDisabled); + } + + let this_instruction = &mut jumps[i]; + + // update biggest/smallest values for next instruction only if it is not after termination. + if !is_after_termination { + this_instruction.smallest = core::cmp::min(this_instruction.smallest, next_smallest); + this_instruction.biggest = core::cmp::max(this_instruction.biggest, next_biggest); + } + + let this_instruction = *this_instruction; + + // Opcodes after termination should be accessed by forward jumps. + if is_after_termination && !this_instruction.is_jumpdest { + // opcode after termination was not accessed. + return Err(EofValidationError::InstructionNotForwardAccessed); + } + is_after_termination = opcode.is_terminating(); + + // mark immediate as non-jumpable. RJUMPV is special case covered later. + if opcode.immediate_size() != 0 { + // check if the opcode immediate are within the bounds of the code + if i + opcode.immediate_size() as usize >= code.len() { + // Malfunctional code + return Err(EofValidationError::MissingImmediateBytes); + } + + // mark immediate bytes as non-jumpable. + for imm in 1..opcode.immediate_size() as usize + 1 { + // SAFETY: immediate size is checked above. + jumps[i + imm].mark_as_immediate()?; + } + } + // IO diff used to generate next instruction smallest/biggest value. + let mut stack_io_diff = opcode.io_diff() as i32; + // how many stack items are required for this opcode. + let mut stack_requirement = opcode.inputs() as i32; + // additional immediate bytes for RJUMPV, it has dynamic vtable. + let mut rjumpv_additional_immediates = 0; + // If opcodes is RJUMP, RJUMPI or RJUMPV then this will have absolute jumpdest. + let mut absolute_jumpdest = vec![]; + match op { + opcode::RJUMP | opcode::RJUMPI => { + let offset = unsafe { read_i16(code.as_ptr().add(i + 1)) } as isize; + absolute_jumpdest = vec![offset + 3 + i as isize]; + // RJUMP is considered a terminating opcode. + } + opcode::RJUMPV => { + // code length for RJUMPV is checked with immediate size. + let max_index = code[i + 1] as usize; + let len = max_index + 1; + // and max_index+1 is to get size of vtable as index starts from 0. + rjumpv_additional_immediates = len * 2; + + // +1 is for max_index byte + if i + 1 + rjumpv_additional_immediates >= code.len() { + // Malfunctional code RJUMPV vtable is not complete + return Err(EofValidationError::MissingRJUMPVImmediateBytes); + } + + // Mark vtable as immediate, max_index was already marked. + for imm in 0..rjumpv_additional_immediates { + // SAFETY: immediate size is checked above. + jumps[i + 2 + imm].mark_as_immediate()?; + } + + let mut jumps = Vec::with_capacity(len); + for vtablei in 0..len { + let offset = + unsafe { read_i16(code.as_ptr().add(i + 2 + 2 * vtablei)) } as isize; + jumps.push(offset + i as isize + 2 + rjumpv_additional_immediates as isize); + } + absolute_jumpdest = jumps + } + opcode::CALLF => { + let section_i = unsafe { read_u16(code.as_ptr().add(i + 1)) } as usize; + let Some(target_types) = types.get(section_i) else { + // code section out of bounds. + return Err(EofValidationError::CodeSectionOutOfBounds); + }; + + if target_types.outputs == EOF_NON_RETURNING_FUNCTION { + // callf to non returning function is not allowed + return Err(EofValidationError::CALLFNonReturningFunction); + } + // stack input for this opcode is the input of the called code. + stack_requirement = target_types.inputs as i32; + // stack diff depends on input/output of the called code. + stack_io_diff = target_types.io_diff(); + // mark called code as accessed. + accessed_codes.insert(section_i); + + // we decrement by `types.inputs` as they are considered as send + // to the called code and included in types.max_stack_size. + if this_instruction.biggest - stack_requirement + target_types.max_stack_size as i32 + > STACK_LIMIT as i32 + { + // if stack max items + called code max stack size + return Err(EofValidationError::StackOverflow); + } + } + opcode::JUMPF => { + let target_index = unsafe { read_u16(code.as_ptr().add(i + 1)) } as usize; + // targeted code needs to have zero outputs (be non returning). + let Some(target_types) = types.get(target_index) else { + // code section out of bounds. + return Err(EofValidationError::CodeSectionOutOfBounds); + }; + + // we decrement types.inputs as they are considered send to the called code. + // and included in types.max_stack_size. + if this_instruction.biggest - target_types.inputs as i32 + + target_types.max_stack_size as i32 + > STACK_LIMIT as i32 + { + // stack overflow + return Err(EofValidationError::StackOverflow); + } + accessed_codes.insert(target_index); + + if target_types.outputs == EOF_NON_RETURNING_FUNCTION { + // if it is not returning + stack_requirement = target_types.inputs as i32; + } else { + // check if target code produces enough outputs. + if this_types.outputs < target_types.outputs { + return Err(EofValidationError::JUMPFEnoughOutputs); + } + + stack_requirement = this_types.outputs as i32 + target_types.inputs as i32 + - target_types.outputs as i32; + + // Stack requirement needs to more than this instruction biggest stack number. + if this_instruction.biggest > stack_requirement { + return Err(EofValidationError::JUMPFStackHigherThanOutputs); + } + + // if this instruction max + target_types max is more then stack limit. + if this_instruction.biggest + stack_requirement > STACK_LIMIT as i32 { + return Err(EofValidationError::StackOverflow); + } + } + } + opcode::EOFCREATE => { + let index = code[i + 1] as usize; + if index >= num_of_containers { + // code section out of bounds. + return Err(EofValidationError::EOFCREATEInvalidIndex); + } + } + opcode::DATALOADN => { + let index = unsafe { read_u16(code.as_ptr().add(i + 1)) } as isize; + if data_size < 32 || index > data_size as isize - 32 { + // data load out of bounds. + return Err(EofValidationError::DataLoadOutOfBounds); + } + } + opcode::RETF => { + stack_requirement = this_types.outputs as i32; + if this_instruction.biggest > stack_requirement { + return Err(EofValidationError::RETFBiggestStackNumMoreThenOutputs); + } + } + opcode::DUPN => { + stack_requirement = code[i + 1] as i32 + 1; + } + opcode::SWAPN => { + stack_requirement = code[i + 1] as i32 + 2; + } + opcode::EXCHANGE => { + let imm = code[i + 1]; + let n = (imm >> 4) + 1; + let m = (imm & 0x0F) + 1; + stack_requirement = n as i32 + m as i32 + 1; + } + _ => {} + } + // check if stack requirement is more than smallest stack items. + if stack_requirement > this_instruction.smallest { + // opcode requirement is more than smallest stack items. + return Err(EofValidationError::StackUnderflow); + } + + next_smallest = this_instruction.smallest + stack_io_diff; + next_biggest = this_instruction.biggest + stack_io_diff; + + // check if jumpdest are correct and mark forward jumps. + for absolute_jump in absolute_jumpdest { + if absolute_jump < 0 { + // jump out of bounds. + return Err(EofValidationError::JumpUnderflow); + } + if absolute_jump >= code.len() as isize { + // jump to out of bounds + return Err(EofValidationError::JumpOverflow); + } + // fine to cast as bounds are checked. + let absolute_jump = absolute_jump as usize; + + let target_jump = &mut jumps[absolute_jump]; + if target_jump.is_immediate { + // Jump target is immediate byte. + return Err(EofValidationError::BackwardJumpToImmediateBytes); + } + + // needed to mark forward jumps. It does not do anything for backward jumps. + target_jump.is_jumpdest = true; + + if absolute_jump <= i { + // backward jumps should have same smallest and biggest stack items. + if target_jump.biggest != next_biggest { + // wrong jumpdest. + return Err(EofValidationError::BackwardJumpBiggestNumMismatch); + } + if target_jump.smallest != next_smallest { + // wrong jumpdest. + return Err(EofValidationError::BackwardJumpSmallestNumMismatch); + } + } else { + // forward jumps can make min even smallest size + // while biggest num is needed to check stack overflow + target_jump.smallest = core::cmp::min(target_jump.smallest, next_smallest); + target_jump.biggest = core::cmp::max(target_jump.biggest, next_biggest); + } + } + + // additional immediate are from RJUMPV vtable. + i += 1 + opcode.immediate_size() as usize + rjumpv_additional_immediates; + } + + // last opcode should be terminating + if !is_after_termination { + // wrong termination. + return Err(EofValidationError::LastInstructionNotTerminating); + } + // TODO integrate max so we dont need to iterate again + let mut max_stack_requirement = 0; + for opcode in jumps { + max_stack_requirement = core::cmp::max(opcode.biggest, max_stack_requirement); + } + + if max_stack_requirement != types[this_types_index].max_stack_size as i32 { + // stack overflow + return Err(EofValidationError::MaxStackMismatch); + } + + Ok(accessed_codes) + } + *) + Definition validate_eof_code (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ code; data_size; this_types_index; num_of_containers; types ] => + ltac:(M.monadic + (let code := M.alloc (| code |) in + let data_size := M.alloc (| data_size |) in + let this_types_index := M.alloc (| this_types_index |) in + let num_of_containers := M.alloc (| num_of_containers |) in + let types := M.alloc (| types |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ accessed_codes := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ Ty.path "usize"; Ty.path "std::hash::random::RandomState" ], + "new", + [] + |), + [] + |) + |) in + let~ this_types := + M.alloc (| + M.SubPointer.get_array_field (| M.read (| types |), this_types_index |) + |) in + let~ jumps := + M.alloc (| + M.call_closure (| + M.get_function (| + "alloc::vec::from_elem", + [ + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo" + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + [], + "default", + [] + |), + [] + |); + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| code |) ] + |) + ] + |) + |) in + let~ is_after_termination := M.alloc (| Value.Bool false |) in + let~ next_smallest := + M.alloc (| + M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| this_types |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)) + |) in + let~ next_biggest := + M.alloc (| + M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| this_types |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)) + |) in + let~ i := M.alloc (| Value.Integer 0 |) in + let~ _ := + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.read (| i |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| code |) ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ op := + M.copy (| + M.SubPointer.get_array_field (| M.read (| code |), i |) + |) in + let~ opcode := + M.alloc (| + M.SubPointer.get_array_field (| + M.get_constant (| + "revm_interpreter::opcode::OPCODE_INFO_JUMPTABLE" + |), + M.alloc (| M.rust_cast (M.read (| op |)) |) + |) + |) in + M.match_operator (| + opcode, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let opcode := M.alloc (| ฮณ1_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "is_disabled_in_eof", + [] + |), + [ M.read (| opcode |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::OpcodeDisabled" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ this_instruction := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo"; + Ty.path "alloc::alloc::Global" + ], + [ Ty.path "usize" ], + "index_mut", + [] + |), + [ jumps; M.read (| i |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| is_after_termination |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| this_instruction |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "smallest" + |), + M.call_closure (| + M.get_function (| + "core::cmp::min", + [ Ty.path "i32" ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| this_instruction |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "smallest" + |) + |); + M.read (| next_smallest |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| this_instruction |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |), + M.call_closure (| + M.get_function (| + "core::cmp::max", + [ Ty.path "i32" ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| this_instruction |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |); + M.read (| next_biggest |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ this_instruction := + M.copy (| M.read (| this_instruction |) |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.read (| is_after_termination |), + ltac:(M.monadic + (UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + this_instruction, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "is_jumpdest" + |) + |)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::InstructionNotForwardAccessed" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + is_after_termination, + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "is_terminating", + [] + |), + [ M.read (| opcode |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ M.read (| opcode |) ] + |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ge + (BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ M.read (| opcode |) ] + |)))) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| code |) ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::MissingImmediateBytes" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 1); + ("end_", + BinOp.Wrap.add + Integer.Usize + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ M.read (| opcode |) ] + |))) + (Value.Integer 1)) + ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.break (||) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let imm := + M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "mark_as_immediate", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo"; + Ty.path + "alloc::alloc::Global" + ], + [ + Ty.path + "usize" + ], + "index_mut", + [] + |), + [ + jumps; + BinOp.Wrap.add + Integer.Usize + (M.read (| + i + |)) + (M.read (| + imm + |)) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := + M.copy (| + ฮณ0_0 + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.apply + (Ty.path + "std::collections::hash::set::HashSet") + [ + Ty.path + "usize"; + Ty.path + "std::hash::random::RandomState" + ]; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| + ฮณ0_0 + |) in + val)) + ] + |) in + M.alloc (| + Value.Tuple [] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ stack_io_diff := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "io_diff", + [] + |), + [ M.read (| opcode |) ] + |)) + |) in + let~ stack_requirement := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "inputs", + [] + |), + [ M.read (| opcode |) ] + |)) + |) in + let~ rjumpv_additional_immediates := + M.alloc (| Value.Integer 0 |) in + let~ absolute_jumpdest := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "isize"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.match_operator (| + op, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 224 + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 225 + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ offset := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_i16", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "*const") + [ Ty.path "u8" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ M.read (| code |) ] + |); + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + ] + |) + ] + |)) + |) in + let~ _ := + M.write (| + absolute_jumpdest, + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "isize" ], + "into_vec", + [ Ty.path "alloc::alloc::Global" ] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.apply + (Ty.path "array") + [ Ty.path "isize" ]; + Ty.path + "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.alloc (| + Value.Array + [ + BinOp.Wrap.add + Integer.Isize + (BinOp.Wrap.add + Integer.Isize + (M.read (| + offset + |)) + (Value.Integer + 3)) + (M.rust_cast + (M.read (| + i + |))) + ] + |) + ] + |) + |)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 226 + |) in + let~ max_index := + M.alloc (| + M.rust_cast + (M.read (| + M.SubPointer.get_array_field (| + M.read (| code |), + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + |) + |) + |)) + |) in + let~ len := + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| max_index |)) + (Value.Integer 1) + |) in + let~ _ := + M.write (| + rjumpv_additional_immediates, + BinOp.Wrap.mul + Integer.Usize + (M.read (| len |)) + (Value.Integer 2) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ge + (BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1)) + (M.read (| + rjumpv_additional_immediates + |))) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| code |) ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::MissingRJUMPVImmediateBytes" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", + M.read (| + rjumpv_additional_immediates + |)) + ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.break (||) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let imm := + M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "mark_as_immediate", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo"; + Ty.path + "alloc::alloc::Global" + ], + [ + Ty.path + "usize" + ], + "index_mut", + [] + |), + [ + jumps; + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| + i + |)) + (Value.Integer + 2)) + (M.read (| + imm + |)) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := + M.copy (| + ฮณ0_0 + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.apply + (Ty.path + "std::collections::hash::set::HashSet") + [ + Ty.path + "usize"; + Ty.path + "std::hash::random::RandomState" + ]; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_interpreter::interpreter::analysis::EofValidationError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| + ฮณ0_0 + |) in + val)) + ] + |) in + M.alloc (| + Value.Tuple [] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ jumps := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "isize"; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ M.read (| len |) ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", M.read (| len |)) + ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.break (||) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let vtablei := + M.copy (| ฮณ0_0 |) in + let~ offset := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_i16", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "*const") + [ + Ty.path + "u8" + ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ], + "as_ptr", + [] + |), + [ + M.read (| + code + |) + ] + |); + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| + i + |)) + (Value.Integer + 2)) + (BinOp.Wrap.mul + Integer.Usize + (Value.Integer + 2) + (M.read (| + vtablei + |))) + ] + |) + ] + |)) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "isize"; + Ty.path + "alloc::alloc::Global" + ], + "push", + [] + |), + [ + jumps; + BinOp.Wrap.add + Integer.Isize + (BinOp.Wrap.add + Integer.Isize + (BinOp.Wrap.add + Integer.Isize + (M.read (| + offset + |)) + (M.rust_cast + (M.read (| + i + |)))) + (Value.Integer + 2)) + (M.rust_cast + (M.read (| + rjumpv_additional_immediates + |))) + ] + |) + |) in + M.alloc (| + Value.Tuple [] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.write (| + absolute_jumpdest, + M.read (| jumps |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 227 + |) in + let~ section_i := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_u16", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "*const") + [ Ty.path "u8" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ M.read (| code |) ] + |); + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + ] + |) + ] + |)) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection" + ], + "get", + [ Ty.path "usize" ] + |), + [ M.read (| types |); M.read (| section_i |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let target_types := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |)) + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::analysis::EOF_NON_RETURNING_FUNCTION" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::CALLFNonReturningFunction" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + stack_requirement, + M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| target_types |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)) + |) in + let~ _ := + M.write (| + stack_io_diff, + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection", + "io_diff", + [] + |), + [ M.read (| target_types |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::set::HashSet") + [ + Ty.path "usize"; + Ty.path + "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + accessed_codes; + M.read (| section_i |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (BinOp.Wrap.add + Integer.I32 + (BinOp.Wrap.sub + Integer.I32 + (M.read (| + M.SubPointer.get_struct_record_field (| + this_instruction, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |)) + (M.read (| + stack_requirement + |))) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |) + |)))) + (M.rust_cast + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::stack::STACK_LIMIT" + |) + |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::StackOverflow" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 229 + |) in + let~ target_index := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_u16", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "*const") + [ Ty.path "u8" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ M.read (| code |) ] + |); + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + ] + |) + ] + |)) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection" + ], + "get", + [ Ty.path "usize" ] + |), + [ + M.read (| types |); + M.read (| target_index |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let target_types := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (BinOp.Wrap.add + Integer.I32 + (BinOp.Wrap.sub + Integer.I32 + (M.read (| + M.SubPointer.get_struct_record_field (| + this_instruction, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |)) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)))) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |) + |)))) + (M.rust_cast + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::stack::STACK_LIMIT" + |) + |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::StackOverflow" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::set::HashSet") + [ + Ty.path "usize"; + Ty.path + "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + accessed_codes; + M.read (| target_index |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |)) + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::analysis::EOF_NON_RETURNING_FUNCTION" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + stack_requirement, + M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| target_types |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + this_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::JUMPFEnoughOutputs" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + let~ _ := + M.write (| + stack_requirement, + BinOp.Wrap.sub + Integer.I32 + (BinOp.Wrap.add + Integer.I32 + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + this_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |))) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)))) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_types + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |))) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| + M.SubPointer.get_struct_record_field (| + this_instruction, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |)) + (M.read (| + stack_requirement + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::JUMPFStackHigherThanOutputs" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (BinOp.Wrap.add + Integer.I32 + (M.read (| + M.SubPointer.get_struct_record_field (| + this_instruction, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |)) + (M.read (| + stack_requirement + |))) + (M.rust_cast + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::stack::STACK_LIMIT" + |) + |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::StackOverflow" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |))) + ] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 236 + |) in + let~ index := + M.alloc (| + M.rust_cast + (M.read (| + M.SubPointer.get_array_field (| + M.read (| code |), + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + |) + |) + |)) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ge + (M.read (| index |)) + (M.read (| num_of_containers |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::EOFCREATEInvalidIndex" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 209 + |) in + let~ index := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_u16", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "*const") + [ Ty.path "u8" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ M.read (| code |) ] + |); + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + ] + |) + ] + |)) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + BinOp.Pure.lt + (M.read (| data_size |)) + (Value.Integer 32), + ltac:(M.monadic + (BinOp.Pure.gt + (M.read (| index |)) + (BinOp.Wrap.sub + Integer.Isize + (M.rust_cast + (M.read (| data_size |))) + (Value.Integer 32)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::DataLoadOutOfBounds" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 228 + |) in + let~ _ := + M.write (| + stack_requirement, + M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| this_types |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |)) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| + M.SubPointer.get_struct_record_field (| + this_instruction, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |)) + (M.read (| stack_requirement |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::RETFBiggestStackNumMoreThenOutputs" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 230 + |) in + let~ _ := + M.write (| + stack_requirement, + BinOp.Wrap.add + Integer.I32 + (M.rust_cast + (M.read (| + M.SubPointer.get_array_field (| + M.read (| code |), + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + |) + |) + |))) + (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 231 + |) in + let~ _ := + M.write (| + stack_requirement, + BinOp.Wrap.add + Integer.I32 + (M.rust_cast + (M.read (| + M.SubPointer.get_array_field (| + M.read (| code |), + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + |) + |) + |))) + (Value.Integer 2) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 232 + |) in + let~ imm := + M.copy (| + M.SubPointer.get_array_field (| + M.read (| code |), + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + |) + |) + |) in + let~ n := + M.alloc (| + BinOp.Wrap.add + Integer.U8 + (BinOp.Wrap.shr + (M.read (| imm |)) + (Value.Integer 4)) + (Value.Integer 1) + |) in + let~ m := + M.alloc (| + BinOp.Wrap.add + Integer.U8 + (BinOp.Pure.bit_and + (M.read (| imm |)) + (Value.Integer 15)) + (Value.Integer 1) + |) in + let~ _ := + M.write (| + stack_requirement, + BinOp.Wrap.add + Integer.I32 + (BinOp.Wrap.add + Integer.I32 + (M.rust_cast (M.read (| n |))) + (M.rust_cast (M.read (| m |)))) + (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| stack_requirement |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + this_instruction, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "smallest" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::StackUnderflow" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + next_smallest, + BinOp.Wrap.add + Integer.I32 + (M.read (| + M.SubPointer.get_struct_record_field (| + this_instruction, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "smallest" + |) + |)) + (M.read (| stack_io_diff |)) + |) in + let~ _ := + M.write (| + next_biggest, + BinOp.Wrap.add + Integer.I32 + (M.read (| + M.SubPointer.get_struct_record_field (| + this_instruction, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |)) + (M.read (| stack_io_diff |)) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "isize"; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| absolute_jumpdest |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "alloc::vec::into_iter::IntoIter") + [ + Ty.path "isize"; + Ty.path "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.break (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let absolute_jump := + M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.read (| + absolute_jump + |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::JumpUnderflow" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ge + (M.read (| + absolute_jump + |)) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ], + "len", + [] + |), + [ + M.read (| + code + |) + ] + |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::JumpOverflow" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + let~ absolute_jump := + M.alloc (| + M.rust_cast + (M.read (| absolute_jump |)) + |) in + let~ target_jump := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo"; + Ty.path + "alloc::alloc::Global" + ], + [ Ty.path "usize" ], + "index_mut", + [] + |), + [ + jumps; + M.read (| absolute_jump |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| + target_jump + |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "is_immediate" + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::BackwardJumpToImmediateBytes" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| target_jump |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "is_jumpdest" + |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.le + (M.read (| + absolute_jump + |)) + (M.read (| i |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_jump + |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |)) + (M.read (| + next_biggest + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Bool + true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::BackwardJumpBiggestNumMismatch" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_jump + |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "smallest" + |) + |)) + (M.read (| + next_smallest + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::BackwardJumpSmallestNumMismatch" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_jump + |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "smallest" + |), + M.call_closure (| + M.get_function (| + "core::cmp::min", + [ Ty.path "i32" ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_jump + |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "smallest" + |) + |); + M.read (| + next_smallest + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_jump + |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |), + M.call_closure (| + M.get_function (| + "core::cmp::max", + [ Ty.path "i32" ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + target_jump + |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |); + M.read (| + next_biggest + |) + ] + |) + |) in + M.alloc (| + Value.Tuple [] + |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + let ฮฒ := i in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (Value.Integer 1) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ M.read (| opcode |) ] + |)))) + (M.read (| rjumpv_additional_immediates |))) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| UnOp.Pure.not (M.read (| is_after_termination |)) |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::LastInstructionNotTerminating" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ max_stack_requirement := M.alloc (| Value.Integer 0 |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo"; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| jumps |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.path + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo"; + Ty.path "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let opcode := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + max_stack_requirement, + M.call_closure (| + M.get_function (| + "core::cmp::max", + [ Ty.path "i32" ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + opcode, + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |); + M.read (| max_stack_requirement |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| max_stack_requirement |)) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_array_field (| + M.read (| types |), + this_types_index + |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |) + |))) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::MaxStackMismatch" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ M.read (| accessed_codes |) ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_validate_eof_code : + M.IsFunction "revm_interpreter::interpreter::analysis::validate_eof_code" validate_eof_code. + + Module validate_eof_code. + (* StructRecord + { + name := "InstructionInfo"; + ty_params := []; + fields := + [ + ("is_immediate", Ty.path "bool"); + ("is_jumpdest", Ty.path "bool"); + ("smallest", Ty.path "i32"); + ("biggest", Ty.path "i32") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "InstructionInfo" |); + M.read (| Value.String "is_immediate" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "is_immediate" + |)); + M.read (| Value.String "is_jumpdest" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "is_jumpdest" + |)); + M.read (| Value.String "smallest" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "smallest" + |)); + M.read (| Value.String "biggest" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "biggest" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + + Module Impl_core_marker_Copy_for_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + + Module Impl_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo". + + (* + fn mark_as_immediate(&mut self) -> Result<(), EofValidationError> { + if self.is_jumpdest { + // Jump to immediate bytes. + return Err(EofValidationError::JumpToImmediateBytes); + } + self.is_immediate = true; + Ok(()) + } + *) + Definition mark_as_immediate (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "is_jumpdest" + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::interpreter::analysis::EofValidationError::JumpToImmediateBytes" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo", + "is_immediate" + |), + Value.Bool true + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_mark_as_immediate : + M.IsAssociatedFunction Self "mark_as_immediate" mark_as_immediate. + End Impl_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + + Module Impl_core_default_Default_for_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo". + + (* + fn default() -> Self { + Self { + is_immediate: false, + is_jumpdest: false, + smallest: i32::MAX, + biggest: i32::MIN, + } + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::interpreter::analysis::validate_eof_code::InstructionInfo" + [ + ("is_immediate", Value.Bool false); + ("is_jumpdest", Value.Bool false); + ("smallest", M.read (| M.get_constant (| "core::num::MAX" |) |)); + ("biggest", M.read (| M.get_constant (| "core::num::MIN" |) |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_interpreter_analysis_validate_eof_code_InstructionInfo. + End validate_eof_code. + End analysis. +End interpreter. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/contract.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/contract.md new file mode 100644 index 00000000..2d33dd5c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/contract.md @@ -0,0 +1,693 @@ +# ๐Ÿ“ contract.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter/contract.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter. + Module contract. + (* StructRecord + { + name := "Contract"; + ty_params := []; + fields := + [ + ("input", Ty.path "alloy_primitives::bytes_::Bytes"); + ("bytecode", Ty.path "revm_primitives::bytecode::Bytecode"); + ("hash", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ]); + ("target_address", Ty.path "alloy_primitives::bits::address::Address"); + ("caller", Ty.path "alloy_primitives::bits::address::Address"); + ("call_value", Ty.path "ruint::Uint") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_contract_Contract. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::contract::Contract". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::interpreter::contract::Contract" + [ + ("input", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "input" + |) + ] + |)); + ("bytecode", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |)); + ("hash", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "hash" + |) + ] + |)); + ("target_address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |) + ] + |)); + ("caller", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "caller" + |) + ] + |)); + ("call_value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "call_value" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_contract_Contract. + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_contract_Contract. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::contract::Contract". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "input" |); + M.read (| Value.String "bytecode" |); + M.read (| Value.String "hash" |); + M.read (| Value.String "target_address" |); + M.read (| Value.String "caller" |); + M.read (| Value.String "call_value" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "input" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "hash" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "target_address" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "caller" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "call_value" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Contract" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_contract_Contract. + + Module Impl_core_default_Default_for_revm_interpreter_interpreter_contract_Contract. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::contract::Contract". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::interpreter::contract::Contract" + [ + ("input", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "default", + [] + |), + [] + |)); + ("bytecode", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "default", + [] + |), + [] + |)); + ("hash", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + [], + "default", + [] + |), + [] + |)); + ("target_address", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bits::address::Address", + [], + "default", + [] + |), + [] + |)); + ("caller", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bits::address::Address", + [], + "default", + [] + |), + [] + |)); + ("call_value", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "ruint::Uint", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_interpreter_contract_Contract. + + Module Impl_revm_interpreter_interpreter_contract_Contract. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::contract::Contract". + + (* + pub fn new( + input: Bytes, + bytecode: Bytecode, + hash: Option, + target_address: Address, + caller: Address, + call_value: U256, + ) -> Self { + let bytecode = to_analysed(bytecode); + + Self { + input, + bytecode, + hash, + target_address, + caller, + call_value, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; bytecode; hash; target_address; caller; call_value ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let bytecode := M.alloc (| bytecode |) in + let hash := M.alloc (| hash |) in + let target_address := M.alloc (| target_address |) in + let caller := M.alloc (| caller |) in + let call_value := M.alloc (| call_value |) in + M.read (| + let~ bytecode := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::interpreter::analysis::to_analysed", [] |), + [ M.read (| bytecode |) ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm_interpreter::interpreter::contract::Contract" + [ + ("input", M.read (| input |)); + ("bytecode", M.read (| bytecode |)); + ("hash", M.read (| hash |)); + ("target_address", M.read (| target_address |)); + ("caller", M.read (| caller |)); + ("call_value", M.read (| call_value |)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn new_env(env: &Env, bytecode: Bytecode, hash: Option) -> Self { + let contract_address = match env.tx.transact_to { + TransactTo::Call(caller) => caller, + TransactTo::Create => Address::ZERO, + }; + Self::new( + env.tx.data.clone(), + bytecode, + hash, + contract_address, + env.tx.caller, + env.tx.value, + ) + } + *) + Definition new_env (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ env; bytecode; hash ] => + ltac:(M.monadic + (let env := M.alloc (| env |) in + let bytecode := M.alloc (| bytecode |) in + let hash := M.alloc (| hash |) in + M.read (| + let~ contract_address := + M.copy (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "transact_to" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + let caller := M.copy (| ฮณ0_0 |) in + caller)); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::env::TransactTo::Create" |) in + M.get_constant (| "alloy_primitives::bits::address::ZERO" |))) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::contract::Contract", + "new", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "data" + |) + ] + |); + M.read (| bytecode |); + M.read (| hash |); + M.read (| contract_address |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "caller" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "value" + |) + |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_env : M.IsAssociatedFunction Self "new_env" new_env. + + (* + pub fn new_with_context( + input: Bytes, + bytecode: Bytecode, + hash: Option, + call_context: &CallInputs, + ) -> Self { + Self::new( + input, + bytecode, + hash, + call_context.target_address, + call_context.caller, + call_context.call_value(), + ) + } + *) + Definition new_with_context (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; bytecode; hash; call_context ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let bytecode := M.alloc (| bytecode |) in + let hash := M.alloc (| hash |) in + let call_context := M.alloc (| call_context |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::contract::Contract", + "new", + [] + |), + [ + M.read (| input |); + M.read (| bytecode |); + M.read (| hash |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| call_context |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| call_context |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "caller" + |) + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "call_value", + [] + |), + [ M.read (| call_context |) ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_with_context : + M.IsAssociatedFunction Self "new_with_context" new_with_context. + + (* + pub fn is_valid_jump(&self, pos: usize) -> bool { + self.bytecode + .legacy_jump_table() + .map(|i| i.is_valid(pos)) + .unwrap_or(false) + } + *) + Definition is_valid_jump (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; pos ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let pos := M.alloc (| pos |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "bool" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable" ] + ], + "map", + [ + Ty.path "bool"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable" ] + ] + ] + (Ty.path "bool") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "legacy_jump_table", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::contract::Contract", + "bytecode" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let i := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::bytecode::legacy::jump_map::JumpTable", + "is_valid", + [] + |), + [ M.read (| i |); M.read (| pos |) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + Value.Bool false + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_valid_jump : + M.IsAssociatedFunction Self "is_valid_jump" is_valid_jump. + End Impl_revm_interpreter_interpreter_contract_Contract. + End contract. +End interpreter. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/shared_memory.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/shared_memory.md new file mode 100644 index 00000000..3eff3601 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/shared_memory.md @@ -0,0 +1,2160 @@ +# ๐Ÿ“ shared_memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter/shared_memory.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter. + Module shared_memory. + (* StructRecord + { + name := "SharedMemory"; + ty_params := []; + fields := + [ + ("buffer", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ]); + ("checkpoints", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ]); + ("last_checkpoint", Ty.path "usize") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::interpreter::shared_memory::SharedMemory" + [ + ("buffer", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |) + ] + |)); + ("checkpoints", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "checkpoints" + |) + ] + |)); + ("last_checkpoint", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "usize", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "checkpoints" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "checkpoints" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + + Module Impl_core_hash_Hash_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "checkpoints" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "usize", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + + Definition value_EMPTY_SHARED_MEMORY : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructRecord + "revm_interpreter::interpreter::shared_memory::SharedMemory" + [ + ("buffer", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [] + |)); + ("checkpoints", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [] + |)); + ("last_checkpoint", Value.Integer 0) + ] + |))). + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SharedMemory") + .field("current_len", &self.len()) + .field( + "context_memory", + &crate::primitives::hex::encode(self.context_memory()), + ) + .finish_non_exhaustive() + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "finish_non_exhaustive", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct", + [] + |), + [ M.read (| f |); M.read (| Value.String "SharedMemory" |) ] + |) + |); + M.read (| Value.String "current_len" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ M.read (| self |) ] + |) + |)) + ] + |); + M.read (| Value.String "context_memory" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_function (| + "const_hex::encode", + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "context_memory", + [] + |), + [ M.read (| self |) ] + |) + ] + |) + |)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + + Module Impl_core_default_Default_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory". + + (* + fn default() -> Self { + Self::new() + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "new", + [] + |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_interpreter_shared_memory_SharedMemory. + + Module Impl_revm_interpreter_interpreter_shared_memory_SharedMemory. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory". + + (* + pub fn new() -> Self { + Self::with_capacity(4 * 1024) // from evmone + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "with_capacity", + [] + |), + [ BinOp.Wrap.mul Integer.Usize (Value.Integer 4) (Value.Integer 1024) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn with_capacity(capacity: usize) -> Self { + Self { + buffer: Vec::with_capacity(capacity), + checkpoints: Vec::with_capacity(32), + last_checkpoint: 0, + #[cfg(feature = "memory_limit")] + memory_limit: u64::MAX, + } + } + *) + Definition with_capacity (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ capacity ] => + ltac:(M.monadic + (let capacity := M.alloc (| capacity |) in + Value.StructRecord + "revm_interpreter::interpreter::shared_memory::SharedMemory" + [ + ("buffer", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "with_capacity", + [] + |), + [ M.read (| capacity |) ] + |)); + ("checkpoints", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ], + "with_capacity", + [] + |), + [ Value.Integer 32 ] + |)); + ("last_checkpoint", Value.Integer 0) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_capacity : + M.IsAssociatedFunction Self "with_capacity" with_capacity. + + (* + pub fn new_context(&mut self) { + let new_checkpoint = self.buffer.len(); + self.checkpoints.push(new_checkpoint); + self.last_checkpoint = new_checkpoint; + } + *) + Definition new_context (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ new_checkpoint := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "checkpoints" + |); + M.read (| new_checkpoint |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |), + M.read (| new_checkpoint |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_context : M.IsAssociatedFunction Self "new_context" new_context. + + (* + pub fn free_context(&mut self) { + if let Some(old_checkpoint) = self.checkpoints.pop() { + self.last_checkpoint = self.checkpoints.last().cloned().unwrap_or_default(); + // SAFETY: buffer length is less than or equal `old_checkpoint` + unsafe { self.buffer.set_len(old_checkpoint) }; + } + } + *) + Definition free_context (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ], + "pop", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "checkpoints" + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let old_checkpoint := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "usize" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "usize" ] ], + "cloned", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "usize" ], + "last", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "usize"; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "checkpoints" + |) + ] + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "set_len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |); + M.read (| old_checkpoint |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_free_context : + M.IsAssociatedFunction Self "free_context" free_context. + + (* + pub fn len(&self) -> usize { + self.buffer.len() - self.last_checkpoint + } + *) + Definition len (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.sub + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |) + ] + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |) + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_len : M.IsAssociatedFunction Self "len" len. + + (* + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + *) + Definition is_empty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ M.read (| self |) ] + |)) + (Value.Integer 0))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_empty : M.IsAssociatedFunction Self "is_empty" is_empty. + + (* + pub fn current_expansion_cost(&self) -> u64 { + crate::gas::memory_gas_for_len(self.len()) + } + *) + Definition current_expansion_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_function (| "revm_interpreter::gas::calc::memory_gas_for_len", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ M.read (| self |) ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_current_expansion_cost : + M.IsAssociatedFunction Self "current_expansion_cost" current_expansion_cost. + + (* + pub fn resize(&mut self, new_size: usize) { + self.buffer.resize(self.last_checkpoint + new_size, 0); + } + *) + Definition resize (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; new_size ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let new_size := M.alloc (| new_size |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "resize", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |); + BinOp.Wrap.add + Integer.Usize + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |) + |)) + (M.read (| new_size |)); + Value.Integer 0 + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_resize : M.IsAssociatedFunction Self "resize" resize. + + (* + pub fn slice(&self, offset: usize, size: usize) -> &[u8] { + self.slice_range(offset..offset + size) + } + *) + Definition slice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset; size ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + let size := M.alloc (| size |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice_range", + [] + |), + [ + M.read (| self |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| offset |)); + ("end_", BinOp.Wrap.add Integer.Usize (M.read (| offset |)) (M.read (| size |))) + ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_slice : M.IsAssociatedFunction Self "slice" slice. + + (* + pub fn slice_range(&self, range @ Range { start, end }: Range) -> &[u8] { + match self.context_memory().get(range) { + Some(slice) => slice, + None => debug_unreachable!("slice OOB: {start}..{end}; len: {}", self.len()), + } + } + *) + Definition slice_range (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; ฮฒ1 ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let ฮฒ1 := M.alloc (| ฮฒ1 |) in + M.match_operator (| + ฮฒ1, + [ + fun ฮณ => + ltac:(M.monadic + (let range := M.copy (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "core::ops::range::Range", + "start" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "core::ops::range::Range", + "end" + |) in + let start := M.copy (| ฮณ1_0 |) in + let end_ := M.copy (| ฮณ1_1 |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "context_memory", + [] + |), + [ M.read (| self |) ] + |); + M.read (| range |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let slice := M.copy (| ฮณ0_0 |) in + M.alloc (| M.read (| slice |) |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: slice OOB: " + |); + M.read (| Value.String ".." |); + M.read (| Value.String "; len: " |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.match_operator (| + M.alloc (| + Value.Tuple + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ M.read (| self |) ] + |) + |); + start; + end_ + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let args := M.copy (| ฮณ |) in + M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_display", + [ Ty.path "usize" ] + |), + [ + M.read (| + M.SubPointer.get_tuple_field (| + args, + 1 + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_display", + [ Ty.path "usize" ] + |), + [ + M.read (| + M.SubPointer.get_tuple_field (| + args, + 2 + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_display", + [ Ty.path "usize" ] + |), + [ + M.read (| + M.SubPointer.get_tuple_field (| + args, + 0 + |) + |) + ] + |) + ] + |))) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::hint::unreachable_unchecked", + [] + |), + [] + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + ] + |) + |))) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_slice_range : M.IsAssociatedFunction Self "slice_range" slice_range. + + (* + pub fn slice_mut(&mut self, offset: usize, size: usize) -> &mut [u8] { + let end = offset + size; + match self.context_memory_mut().get_mut(offset..end) { + Some(slice) => slice, + None => debug_unreachable!("slice OOB: {offset}..{end}"), + } + } + *) + Definition slice_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset; size ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + let size := M.alloc (| size |) in + M.read (| + let~ end_ := + M.alloc (| + BinOp.Wrap.add Integer.Usize (M.read (| offset |)) (M.read (| size |)) + |) in + M.alloc (| + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get_mut", + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "context_memory_mut", + [] + |), + [ M.read (| self |) ] + |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", M.read (| offset |)); ("end_", M.read (| end_ |)) ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let slice := M.copy (| ฮณ0_0 |) in + M.alloc (| M.read (| slice |) |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: slice OOB: " + |); + M.read (| Value.String ".." |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.path "usize" ] + |), + [ offset ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.path "usize" ] + |), + [ end_ ] + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::hint::unreachable_unchecked", + [] + |), + [] + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + ] + |) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_slice_mut : M.IsAssociatedFunction Self "slice_mut" slice_mut. + + (* + pub fn get_byte(&self, offset: usize) -> u8 { + self.slice(offset, 1)[0] + } + *) + Definition get_byte (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + M.read (| + M.SubPointer.get_array_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice", + [] + |), + [ M.read (| self |); M.read (| offset |); Value.Integer 1 ] + |), + M.alloc (| Value.Integer 0 |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get_byte : M.IsAssociatedFunction Self "get_byte" get_byte. + + (* + pub fn get_word(&self, offset: usize) -> B256 { + self.slice(offset, 32).try_into().unwrap() + } + *) + Definition get_word (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "try_into", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice", + [] + |), + [ M.read (| self |); M.read (| offset |); Value.Integer 32 ] + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get_word : M.IsAssociatedFunction Self "get_word" get_word. + + (* + pub fn get_u256(&self, offset: usize) -> U256 { + self.get_word(offset).into() + } + *) + Definition get_u256 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "into", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "get_word", + [] + |), + [ M.read (| self |); M.read (| offset |) ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get_u256 : M.IsAssociatedFunction Self "get_u256" get_u256. + + (* + pub fn set_byte(&mut self, offset: usize, byte: u8) { + self.set(offset, &[byte]); + } + *) + Definition set_byte (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset; byte ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + let byte := M.alloc (| byte |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set", + [] + |), + [ + M.read (| self |); + M.read (| offset |); + (* Unsize *) + M.pointer_coercion (M.alloc (| Value.Array [ M.read (| byte |) ] |)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_byte : M.IsAssociatedFunction Self "set_byte" set_byte. + + (* + pub fn set_word(&mut self, offset: usize, value: &B256) { + self.set(offset, &value[..]); + } + *) + Definition set_word (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + let value := M.alloc (| value |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set", + [] + |), + [ + M.read (| self |); + M.read (| offset |); + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "core::ops::range::RangeFull" ], + "index", + [] + |), + [ M.read (| value |); Value.StructTuple "core::ops::range::RangeFull" [] ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_word : M.IsAssociatedFunction Self "set_word" set_word. + + (* + pub fn set_u256(&mut self, offset: usize, value: U256) { + self.set(offset, &value.to_be_bytes::<32>()); + } + *) + Definition set_u256 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + let value := M.alloc (| value |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "set", + [] + |), + [ + M.read (| self |); + M.read (| offset |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "to_be_bytes", + [] + |), + [ value ] + |) + |)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_u256 : M.IsAssociatedFunction Self "set_u256" set_u256. + + (* + pub fn set(&mut self, offset: usize, value: &[u8]) { + if !value.is_empty() { + self.slice_mut(offset, value.len()).copy_from_slice(value); + } + } + *) + Definition set (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + let value := M.alloc (| value |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "is_empty", + [] + |), + [ M.read (| value |) ] + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice_mut", + [] + |), + [ + M.read (| self |); + M.read (| offset |); + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| value |) ] + |) + ] + |); + M.read (| value |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set : M.IsAssociatedFunction Self "set" set. + + (* + pub fn set_data(&mut self, memory_offset: usize, data_offset: usize, len: usize, data: &[u8]) { + if data_offset >= data.len() { + // nullify all memory slots + self.slice_mut(memory_offset, len).fill(0); + return; + } + let data_end = min(data_offset + len, data.len()); + let data_len = data_end - data_offset; + debug_assert!(data_offset < data.len() && data_end <= data.len()); + let data = unsafe { data.get_unchecked(data_offset..data_end) }; + self.slice_mut(memory_offset, data_len) + .copy_from_slice(data); + + // nullify rest of memory slots + // SAFETY: Memory is assumed to be valid, and it is commented where this assumption is made. + self.slice_mut(memory_offset + data_len, len - data_len) + .fill(0); + } + *) + Definition set_data (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; memory_offset; data_offset; len; data ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let memory_offset := M.alloc (| memory_offset |) in + let data_offset := M.alloc (| data_offset |) in + let len := M.alloc (| len |) in + let data := M.alloc (| data |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ge + (M.read (| data_offset |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| data |) ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "fill", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice_mut", + [] + |), + [ + M.read (| self |); + M.read (| memory_offset |); + M.read (| len |) + ] + |); + Value.Integer 0 + ] + |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ data_end := + M.alloc (| + M.call_closure (| + M.get_function (| "core::cmp::min", [ Ty.path "usize" ] |), + [ + BinOp.Wrap.add + Integer.Usize + (M.read (| data_offset |)) + (M.read (| len |)); + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| data |) ] + |) + ] + |) + |) in + let~ data_len := + M.alloc (| + BinOp.Wrap.sub + Integer.Usize + (M.read (| data_end |)) + (M.read (| data_offset |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.and (| + BinOp.Pure.lt + (M.read (| data_offset |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| data |) ] + |)), + ltac:(M.monadic + (BinOp.Pure.le + (M.read (| data_end |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| data |) ] + |)))) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic", [] |), + [ + M.read (| + Value.String + "assertion failed: data_offset < data.len() && data_end <= data.len()" + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ data := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get_unchecked", + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ] + |), + [ + M.read (| data |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", M.read (| data_offset |)); ("end_", M.read (| data_end |)) ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice_mut", + [] + |), + [ M.read (| self |); M.read (| memory_offset |); M.read (| data_len |) ] + |); + M.read (| data |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "fill", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "slice_mut", + [] + |), + [ + M.read (| self |); + BinOp.Wrap.add + Integer.Usize + (M.read (| memory_offset |)) + (M.read (| data_len |)); + BinOp.Wrap.sub + Integer.Usize + (M.read (| len |)) + (M.read (| data_len |)) + ] + |); + Value.Integer 0 + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_data : M.IsAssociatedFunction Self "set_data" set_data. + + (* + pub fn copy(&mut self, dst: usize, src: usize, len: usize) { + self.context_memory_mut().copy_within(src..src + len, dst); + } + *) + Definition copy (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; dst; src; len ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let dst := M.alloc (| dst |) in + let src := M.alloc (| src |) in + let len := M.alloc (| len |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_within", + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "context_memory_mut", + [] + |), + [ M.read (| self |) ] + |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| src |)); + ("end_", + BinOp.Wrap.add Integer.Usize (M.read (| src |)) (M.read (| len |))) + ]; + M.read (| dst |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_copy : M.IsAssociatedFunction Self "copy" copy. + + (* + pub fn context_memory(&self) -> &[u8] { + // SAFETY: access bounded by buffer length + unsafe { + self.buffer + .get_unchecked(self.last_checkpoint..self.buffer.len()) + } + } + *) + Definition context_memory (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get_unchecked", + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |) + ] + |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |) + |)); + ("end_", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |) + ] + |)) + ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_context_memory : + M.IsAssociatedFunction Self "context_memory" context_memory. + + (* + pub fn context_memory_mut(&mut self) -> &mut [u8] { + let buf_len = self.buffer.len(); + // SAFETY: access bounded by buffer length + unsafe { self.buffer.get_unchecked_mut(self.last_checkpoint..buf_len) } + } + *) + Definition context_memory_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ buf_len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get_unchecked_mut", + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "buffer" + |) + ] + |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "last_checkpoint" + |) + |)); + ("end_", M.read (| buf_len |)) + ] + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_context_memory_mut : + M.IsAssociatedFunction Self "context_memory_mut" context_memory_mut. + End Impl_revm_interpreter_interpreter_shared_memory_SharedMemory. + + (* + pub const fn num_words(len: u64) -> u64 { + len.saturating_add(31) / 32 + } + *) + Definition num_words (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ len ] => + ltac:(M.monadic + (let len := M.alloc (| len |) in + BinOp.Wrap.div + Integer.U64 + (M.call_closure (| + M.get_associated_function (| Ty.path "u64", "saturating_add", [] |), + [ M.read (| len |); Value.Integer 31 ] + |)) + (Value.Integer 32))) + | _, _ => M.impossible + end. + + Axiom Function_num_words : + M.IsFunction "revm_interpreter::interpreter::shared_memory::num_words" num_words. + End shared_memory. +End interpreter. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/stack.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/stack.md new file mode 100644 index 00000000..46e99f93 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter/stack.md @@ -0,0 +1,3427 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter/stack.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter. + Module stack. + Definition value_STACK_LIMIT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 1024 |))). + + (* StructRecord + { + name := "Stack"; + ty_params := []; + fields := + [ + ("data", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ]) + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_stack_Stack. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::stack::Stack". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Stack" |); + M.read (| Value.String "data" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_stack_Stack. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_stack_Stack. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::stack::Stack". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_stack_Stack. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_stack_Stack. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::stack::Stack". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_stack_Stack. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_stack_Stack. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::stack::Stack". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_stack_Stack. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_stack_Stack. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::stack::Stack". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_stack_Stack. + + Module Impl_core_hash_Hash_for_revm_interpreter_interpreter_stack_Stack. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::stack::Stack". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |); + M.read (| state |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_interpreter_stack_Stack. + + Module Impl_core_fmt_Display_for_revm_interpreter_interpreter_stack_Stack. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::stack::Stack". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("[")?; + for (i, x) in self.data.iter().enumerate() { + if i > 0 { + f.write_str(", ")?; + } + write!(f, "{x}")?; + } + f.write_str("]") + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.path "core::fmt::Error" ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "[" |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.path "core::fmt::Error" ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "core::fmt::Error" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::iter::adapters::enumerate::Enumerate") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "ruint::Uint" ] + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "ruint::Uint" ], + [], + "enumerate", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "ruint::Uint" ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::enumerate::Enumerate") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "ruint::Uint" ] + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let i := M.copy (| ฮณ1_0 |) in + let x := M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| i |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path "core::fmt::Error" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ + M.read (| f |); + M.read (| Value.String ", " |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple []; + Ty.path + "core::fmt::Error" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "core::fmt::Error" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.path "core::fmt::Error" ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "" |) ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_display", + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "ruint::Uint" + ] + ] + |), + [ x ] + |) + ] + |)) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path "core::fmt::Error" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path "core::fmt::Error" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "]" |) ] + |) + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Display" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Display_for_revm_interpreter_interpreter_stack_Stack. + + Module Impl_core_default_Default_for_revm_interpreter_interpreter_stack_Stack. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::stack::Stack". + + (* + fn default() -> Self { + Self::new() + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "new", + [] + |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_interpreter_stack_Stack. + + Module Impl_revm_interpreter_interpreter_stack_Stack. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter::stack::Stack". + + (* + pub fn new() -> Self { + Self { + // SAFETY: expansion functions assume that capacity is `STACK_LIMIT`. + data: Vec::with_capacity(STACK_LIMIT), + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::interpreter::stack::Stack" + [ + ("data", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "with_capacity", + [] + |), + [ + M.read (| + M.get_constant (| "revm_interpreter::interpreter::stack::STACK_LIMIT" |) + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn len(&self) -> usize { + self.data.len() + } + *) + Definition len (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_len : M.IsAssociatedFunction Self "len" len. + + (* + pub fn is_empty(&self) -> bool { + self.data.is_empty() + } + *) + Definition is_empty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_empty : M.IsAssociatedFunction Self "is_empty" is_empty. + + (* + pub fn data(&self) -> &Vec { + &self.data + } + *) + Definition data (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_data : M.IsAssociatedFunction Self "data" data. + + (* + pub fn data_mut(&mut self) -> &mut Vec { + &mut self.data + } + *) + Definition data_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_data_mut : M.IsAssociatedFunction Self "data_mut" data_mut. + + (* + pub fn into_data(self) -> Vec { + self.data + } + *) + Definition into_data (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_data : M.IsAssociatedFunction Self "into_data" into_data. + + (* + pub fn pop(&mut self) -> Result { + self.data.pop().ok_or(InstructionResult::StackUnderflow) + } + *) + Definition pop (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "ok_or", + [ Ty.path "revm_interpreter::instruction_result::InstructionResult" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "pop", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |); + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop : M.IsAssociatedFunction Self "pop" pop. + + (* + pub unsafe fn pop_unsafe(&mut self) -> U256 { + self.data.pop().unwrap_unchecked() + } + *) + Definition pop_unsafe (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "unwrap_unchecked", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "pop", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop_unsafe : M.IsAssociatedFunction Self "pop_unsafe" pop_unsafe. + + (* + pub unsafe fn top_unsafe(&mut self) -> &mut U256 { + let len = self.data.len(); + self.data.get_unchecked_mut(len - 1) + } + *) + Definition top_unsafe (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "ruint::Uint" ], + "get_unchecked_mut", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |); + BinOp.Wrap.sub Integer.Usize (M.read (| len |)) (Value.Integer 1) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_top_unsafe : M.IsAssociatedFunction Self "top_unsafe" top_unsafe. + + (* + pub unsafe fn pop_top_unsafe(&mut self) -> (U256, &mut U256) { + let pop = self.pop_unsafe(); + let top = self.top_unsafe(); + (pop, top) + } + *) + Definition pop_top_unsafe (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ pop := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ top := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| Value.Tuple [ M.read (| pop |); M.read (| top |) ] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop_top_unsafe : + M.IsAssociatedFunction Self "pop_top_unsafe" pop_top_unsafe. + + (* + pub unsafe fn pop2_unsafe(&mut self) -> (U256, U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + (pop1, pop2) + } + *) + Definition pop2_unsafe (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ pop1 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop2 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| Value.Tuple [ M.read (| pop1 |); M.read (| pop2 |) ] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop2_unsafe : M.IsAssociatedFunction Self "pop2_unsafe" pop2_unsafe. + + (* + pub unsafe fn pop2_top_unsafe(&mut self) -> (U256, U256, &mut U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + let top = self.top_unsafe(); + + (pop1, pop2, top) + } + *) + Definition pop2_top_unsafe (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ pop1 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop2 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ top := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "top_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| Value.Tuple [ M.read (| pop1 |); M.read (| pop2 |); M.read (| top |) ] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop2_top_unsafe : + M.IsAssociatedFunction Self "pop2_top_unsafe" pop2_top_unsafe. + + (* + pub unsafe fn pop3_unsafe(&mut self) -> (U256, U256, U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + let pop3 = self.pop_unsafe(); + + (pop1, pop2, pop3) + } + *) + Definition pop3_unsafe (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ pop1 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop2 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop3 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| Value.Tuple [ M.read (| pop1 |); M.read (| pop2 |); M.read (| pop3 |) ] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop3_unsafe : M.IsAssociatedFunction Self "pop3_unsafe" pop3_unsafe. + + (* + pub unsafe fn pop4_unsafe(&mut self) -> (U256, U256, U256, U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + let pop3 = self.pop_unsafe(); + let pop4 = self.pop_unsafe(); + + (pop1, pop2, pop3, pop4) + } + *) + Definition pop4_unsafe (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ pop1 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop2 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop3 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop4 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + Value.Tuple + [ M.read (| pop1 |); M.read (| pop2 |); M.read (| pop3 |); M.read (| pop4 |) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop4_unsafe : M.IsAssociatedFunction Self "pop4_unsafe" pop4_unsafe. + + (* + pub unsafe fn pop5_unsafe(&mut self) -> (U256, U256, U256, U256, U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + let pop3 = self.pop_unsafe(); + let pop4 = self.pop_unsafe(); + let pop5 = self.pop_unsafe(); + + (pop1, pop2, pop3, pop4, pop5) + } + *) + Definition pop5_unsafe (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ pop1 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop2 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop3 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop4 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ pop5 := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "pop_unsafe", + [] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + Value.Tuple + [ + M.read (| pop1 |); + M.read (| pop2 |); + M.read (| pop3 |); + M.read (| pop4 |); + M.read (| pop5 |) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop5_unsafe : M.IsAssociatedFunction Self "pop5_unsafe" pop5_unsafe. + + (* + pub fn push_b256(&mut self, value: B256) -> Result<(), InstructionResult> { + self.push(value.into()) + } + *) + Definition push_b256 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let value := M.alloc (| value |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "push", + [] + |), + [ + M.read (| self |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "ruint::Uint" ], + "into", + [] + |), + [ M.read (| value |) ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_push_b256 : M.IsAssociatedFunction Self "push_b256" push_b256. + + (* + pub fn push(&mut self, value: U256) -> Result<(), InstructionResult> { + // Allows the compiler to optimize out the `Vec::push` capacity check. + assume!(self.data.capacity() == STACK_LIMIT); + if self.data.len() == STACK_LIMIT { + return Err(InstructionResult::StackOverflow); + } + self.data.push(value); + Ok(()) + } + *) + Definition push (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let value := M.alloc (| value |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" + ], + "capacity", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |)) + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::stack::STACK_LIMIT" + |) + |))) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic_fmt", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: self.data.capacity() == STACK_LIMIT" + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "none", + [] + |), + [] + |) + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::hint::unreachable_unchecked", + [] + |), + [] + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |)) + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::stack::STACK_LIMIT" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackOverflow" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |); + M.read (| value |) + ] + |) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_push : M.IsAssociatedFunction Self "push" push. + + (* + pub fn peek(&self, no_from_top: usize) -> Result { + if self.data.len() > no_from_top { + Ok(self.data[self.data.len() - no_from_top - 1]) + } else { + Err(InstructionResult::StackUnderflow) + } + } + *) + Definition peek (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; no_from_top ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let no_from_top := M.alloc (| no_from_top |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |)) + (M.read (| no_from_top |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.read (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "usize" ], + "index", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |); + BinOp.Wrap.sub + Integer.Usize + (BinOp.Wrap.sub + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |)) + (M.read (| no_from_top |))) + (Value.Integer 1) + ] + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_peek : M.IsAssociatedFunction Self "peek" peek. + + (* + pub fn dup(&mut self, n: usize) -> Result<(), InstructionResult> { + assume!(n > 0, "attempted to dup 0"); + let len = self.data.len(); + if len < n { + Err(InstructionResult::StackUnderflow) + } else if len + 1 > STACK_LIMIT { + Err(InstructionResult::StackOverflow) + } else { + // SAFETY: check for out of bounds is done above and it makes this safe to do. + unsafe { + let ptr = self.data.as_mut_ptr().add(len); + ptr::copy_nonoverlapping(ptr.sub(n), ptr, 1); + self.data.set_len(len + 1); + } + Ok(()) + } + } + *) + Definition dup (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; n ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let n := M.alloc (| n |) in + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not (BinOp.Pure.gt (M.read (| n |)) (Value.Integer 0)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: attempted to dup 0" + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "none", + [] + |), + [] + |) + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::hint::unreachable_unchecked", + [] + |), + [] + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use (M.alloc (| BinOp.Pure.lt (M.read (| len |)) (M.read (| n |)) |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (BinOp.Wrap.add + Integer.Usize + (M.read (| len |)) + (Value.Integer 1)) + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::stack::STACK_LIMIT" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackOverflow" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + let~ ptr := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "ruint::Uint" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ], + "as_mut_ptr", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |); + M.read (| len |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::copy_nonoverlapping", + [ Ty.path "ruint::Uint" ] + |), + [ + (* MutToConstPointer *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "ruint::Uint" ], + "sub", + [] + |), + [ M.read (| ptr |); M.read (| n |) ] + |)); + M.read (| ptr |); + Value.Integer 1 + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "set_len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |); + BinOp.Wrap.add + Integer.Usize + (M.read (| len |)) + (Value.Integer 1) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_dup : M.IsAssociatedFunction Self "dup" dup. + + (* + pub fn swap(&mut self, n: usize) -> Result<(), InstructionResult> { + self.exchange(0, n) + } + *) + Definition swap (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; n ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let n := M.alloc (| n |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "exchange", + [] + |), + [ M.read (| self |); Value.Integer 0; M.read (| n |) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_swap : M.IsAssociatedFunction Self "swap" swap. + + (* + pub fn exchange(&mut self, n: usize, m: usize) -> Result<(), InstructionResult> { + assume!(m > 0, "overlapping exchange"); + let len = self.data.len(); + let n_m_index = n + m; + if n_m_index >= len { + return Err(InstructionResult::StackUnderflow); + } + // SAFETY: `n` and `n_m` are checked to be within bounds, and they don't overlap. + unsafe { + // NOTE: `ptr::swap_nonoverlapping` is more efficient than `slice::swap` or `ptr::swap` + // because it operates under the assumption that the pointers do not overlap, + // eliminating an intemediate copy, + // which is a condition we know to be true in this context. + let top = self.data.as_mut_ptr().add(len - 1); + core::ptr::swap_nonoverlapping(top.sub(n), top.sub(n_m_index), 1); + } + Ok(()) + } + *) + Definition exchange (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; n; m ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let n := M.alloc (| n |) in + let m := M.alloc (| m |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not (BinOp.Pure.gt (M.read (| m |)) (Value.Integer 0)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic_fmt", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: overlapping exchange" + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "none", + [] + |), + [] + |) + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::hint::unreachable_unchecked", + [] + |), + [] + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |) + |) in + let~ n_m_index := + M.alloc (| BinOp.Wrap.add Integer.Usize (M.read (| n |)) (M.read (| m |)) |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ge (M.read (| n_m_index |)) (M.read (| len |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + let~ top := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "ruint::Uint" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "as_mut_ptr", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |); + BinOp.Wrap.sub Integer.Usize (M.read (| len |)) (Value.Integer 1) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::ptr::swap_nonoverlapping", + [ Ty.path "ruint::Uint" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "ruint::Uint" ], + "sub", + [] + |), + [ M.read (| top |); M.read (| n |) ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "ruint::Uint" ], + "sub", + [] + |), + [ M.read (| top |); M.read (| n_m_index |) ] + |); + Value.Integer 1 + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_exchange : M.IsAssociatedFunction Self "exchange" exchange. + + (* + pub fn push_slice(&mut self, slice: &[u8]) -> Result<(), InstructionResult> { + if slice.is_empty() { + return Ok(()); + } + + let n_words = (slice.len() + 31) / 32; + let new_len = self.data.len() + n_words; + if new_len > STACK_LIMIT { + return Err(InstructionResult::StackOverflow); + } + + // SAFETY: length checked above. + unsafe { + let dst = self.data.as_mut_ptr().add(self.data.len()).cast::(); + self.data.set_len(new_len); + + let mut i = 0; + + // write full words + let words = slice.chunks_exact(32); + let partial_last_word = words.remainder(); + for word in words { + // Note: we unroll `U256::from_be_bytes` here to write directly into the buffer, + // instead of creating a 32 byte array on the stack and then copying it over. + for l in word.rchunks_exact(8) { + dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap())); + i += 1; + } + } + + if partial_last_word.is_empty() { + return Ok(()); + } + + // write limbs of partial last word + let limbs = partial_last_word.rchunks_exact(8); + let partial_last_limb = limbs.remainder(); + for l in limbs { + dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap())); + i += 1; + } + + // write partial last limb by padding with zeros + if !partial_last_limb.is_empty() { + let mut tmp = [0u8; 8]; + tmp[8 - partial_last_limb.len()..].copy_from_slice(partial_last_limb); + dst.add(i).write(u64::from_be_bytes(tmp)); + i += 1; + } + + debug_assert_eq!((i + 3) / 4, n_words, "wrote too much"); + + // zero out upper bytes of last word + let m = i % 4; // 32 / 8 + if m != 0 { + dst.add(i).write_bytes(0, 4 - m); + } + } + + Ok(()) + } + *) + Definition push_slice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; slice ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let slice := M.alloc (| slice |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "is_empty", + [] + |), + [ M.read (| slice |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ n_words := + M.alloc (| + BinOp.Wrap.div + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| slice |) ] + |)) + (Value.Integer 31)) + (Value.Integer 32) + |) in + let~ new_len := + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |)) + (M.read (| n_words |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| new_len |)) + (M.read (| + M.get_constant (| + "revm_interpreter::interpreter::stack::STACK_LIMIT" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackOverflow" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + let~ dst := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "ruint::Uint" ], + "cast", + [ Ty.path "u64" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "ruint::Uint" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "as_mut_ptr", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "set_len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |); + M.read (| new_len |) + ] + |) + |) in + let~ i := M.alloc (| Value.Integer 0 |) in + let~ words := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "chunks_exact", + [] + |), + [ M.read (| slice |); Value.Integer 32 ] + |) + |) in + let~ partial_last_word := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::slice::iter::ChunksExact") [ Ty.path "u8" ], + "remainder", + [] + |), + [ words ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::slice::iter::ChunksExact") + [ Ty.path "u8" ], + [], + "into_iter", + [] + |), + [ M.read (| words |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::ChunksExact") + [ Ty.path "u8" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let word := M.copy (| ฮณ0_0 |) in + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "core::slice::iter::RChunksExact") + [ Ty.path "u8" ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "rchunks_exact", + [] + |), + [ M.read (| word |); Value.Integer 8 ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::slice::iter::RChunksExact") + [ Ty.path "u8" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.break (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let l := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "*mut") + [ Ty.path "u64" ], + "write", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "*mut") + [ Ty.path "u64" + ], + "add", + [] + |), + [ + M.read (| dst |); + M.read (| i |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "from_be_bytes", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.apply + (Ty.path + "array") + [ + Ty.path + "u8" + ]; + Ty.path + "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ], + [ + Ty.apply + (Ty.path + "array") + [ + Ty.path + "u8" + ] + ], + "try_into", + [] + |), + [ + M.read (| + l + |) + ] + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + let ฮฒ := i in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "is_empty", + [] + |), + [ M.read (| partial_last_word |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ Value.Tuple [] ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ limbs := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "rchunks_exact", + [] + |), + [ M.read (| partial_last_word |); Value.Integer 8 ] + |) + |) in + let~ partial_last_limb := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::slice::iter::RChunksExact") [ Ty.path "u8" ], + "remainder", + [] + |), + [ limbs ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::slice::iter::RChunksExact") + [ Ty.path "u8" ], + [], + "into_iter", + [] + |), + [ M.read (| limbs |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::RChunksExact") + [ Ty.path "u8" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let l := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "u64" ], + "write", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "*mut") + [ Ty.path "u64" ], + "add", + [] + |), + [ M.read (| dst |); M.read (| i |) ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "from_be_bytes", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "array") + [ Ty.path "u8" ]; + Ty.path + "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ], + [ + Ty.apply + (Ty.path "array") + [ Ty.path "u8" ] + ], + "try_into", + [] + |), + [ M.read (| l |) ] + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + let ฮฒ := i in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "is_empty", + [] + |), + [ M.read (| partial_last_limb |) ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ tmp := M.alloc (| repeat (Value.Integer 0) 8 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeFrom") + [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + tmp; + Value.StructRecord + "core::ops::range::RangeFrom" + [ + ("start", + BinOp.Wrap.sub + Integer.Usize + (Value.Integer 8) + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| partial_last_limb |) ] + |))) + ] + ] + |); + M.read (| partial_last_limb |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "u64" ], + "write", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "u64" ], + "add", + [] + |), + [ M.read (| dst |); M.read (| i |) ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "from_be_bytes", + [] + |), + [ M.read (| tmp |) ] + |) + ] + |) + |) in + let~ _ := + let ฮฒ := i in + M.write (| + ฮฒ, + BinOp.Wrap.add Integer.Usize (M.read (| ฮฒ |)) (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use (M.alloc (| Value.Bool true |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| + Value.Tuple + [ + M.alloc (| + BinOp.Wrap.div + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 3)) + (Value.Integer 4) + |); + n_words + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let left_val := M.copy (| ฮณ0_0 |) in + let right_val := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (BinOp.Pure.eq + (M.read (| M.read (| left_val |) |)) + (M.read (| M.read (| right_val |) |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ kind := + M.alloc (| + Value.StructTuple + "core::panicking::AssertKind::Eq" + [] + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "core::panicking::assert_failed", + [ Ty.path "usize"; Ty.path "usize" ] + |), + [ + M.read (| kind |); + M.read (| left_val |); + M.read (| right_val |); + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "wrote too much" + |) + ] + |)) + ] + |) + ] + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ m := + M.alloc (| + BinOp.Wrap.rem Integer.Usize (M.read (| i |)) (Value.Integer 4) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| BinOp.Pure.ne (M.read (| m |)) (Value.Integer 0) |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "u64" ], + "write_bytes", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*mut") [ Ty.path "u64" ], + "add", + [] + |), + [ M.read (| dst |); M.read (| i |) ] + |); + Value.Integer 0; + BinOp.Wrap.sub Integer.Usize (Value.Integer 4) (M.read (| m |)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_push_slice : M.IsAssociatedFunction Self "push_slice" push_slice. + + (* + pub fn set(&mut self, no_from_top: usize, val: U256) -> Result<(), InstructionResult> { + if self.data.len() > no_from_top { + let len = self.data.len(); + self.data[len - no_from_top - 1] = val; + Ok(()) + } else { + Err(InstructionResult::StackUnderflow) + } + } + *) + Definition set (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; no_from_top; val ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let no_from_top := M.alloc (| no_from_top |) in + let val := M.alloc (| val |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |)) + (M.read (| no_from_top |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "usize" ], + "index_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter::stack::Stack", + "data" + |); + BinOp.Wrap.sub + Integer.Usize + (BinOp.Wrap.sub + Integer.Usize + (M.read (| len |)) + (M.read (| no_from_top |))) + (Value.Integer 1) + ] + |), + M.read (| val |) + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::StackUnderflow" + [] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set : M.IsAssociatedFunction Self "set" set. + End Impl_revm_interpreter_interpreter_stack_Stack. + End stack. +End interpreter. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action.md new file mode 100644 index 00000000..7b1b5cce --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action.md @@ -0,0 +1,902 @@ +# ๐Ÿ“ interpreter_action.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter_action.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter_action. + (* + Enum InterpreterAction + { + ty_params := []; + variants := + [ + { + name := "Call"; + item := + StructRecord + [ + ("inputs", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ]) + ]; + discriminant := None; + }; + { + name := "Create"; + item := + StructRecord + [ + ("inputs", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ]) + ]; + discriminant := None; + }; + { + name := "EOFCreate"; + item := + StructRecord + [ + ("inputs", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ]) + ]; + discriminant := None; + }; + { + name := "Return"; + item := + StructRecord [ ("result", Ty.path "revm_interpreter::interpreter::InterpreterResult") ]; + discriminant := None; + }; + { + name := "None"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_InterpreterAction. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter_action::InterpreterAction". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Call", + "inputs" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Call" + [ + ("inputs", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Create", + "inputs" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Create" + [ + ("inputs", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate", + "inputs" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate" + [ + ("inputs", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Return", + "result" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructRecord + "revm_interpreter::interpreter_action::InterpreterAction::Return" + [ + ("result", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_interpreter::interpreter::InterpreterResult", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::None" + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::interpreter_action::InterpreterAction::None" + [] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_InterpreterAction. + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_InterpreterAction. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter_action::InterpreterAction". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Call", + "inputs" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Call" |); + M.read (| Value.String "inputs" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Create", + "inputs" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Create" |); + M.read (| Value.String "inputs" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate", + "inputs" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "EOFCreate" |); + M.read (| Value.String "inputs" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Return", + "result" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Return" |); + M.read (| Value.String "result" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::None" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "None" |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_InterpreterAction. + + Module Impl_core_default_Default_for_revm_interpreter_interpreter_action_InterpreterAction. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter_action::InterpreterAction". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple "revm_interpreter::interpreter_action::InterpreterAction::None" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_interpreter_action_InterpreterAction. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_InterpreterAction. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter_action::InterpreterAction". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_InterpreterAction. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_InterpreterAction. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter_action::InterpreterAction". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter_action::InterpreterAction" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter_action::InterpreterAction" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::interpreter_action::InterpreterAction::Call", + "inputs" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_interpreter::interpreter_action::InterpreterAction::Call", + "inputs" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::interpreter_action::InterpreterAction::Create", + "inputs" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_interpreter::interpreter_action::InterpreterAction::Create", + "inputs" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate", + "inputs" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate", + "inputs" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_interpreter::interpreter_action::InterpreterAction::Return", + "result" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_interpreter::interpreter_action::InterpreterAction::Return", + "result" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::interpreter::InterpreterResult", + [ Ty.path "revm_interpreter::interpreter::InterpreterResult" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool true |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_InterpreterAction. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_InterpreterAction. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter_action::InterpreterAction". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_InterpreterAction. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_InterpreterAction. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter_action::InterpreterAction". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_InterpreterAction. + + Module Impl_revm_interpreter_interpreter_action_InterpreterAction. + Definition Self : Ty.t := Ty.path "revm_interpreter::interpreter_action::InterpreterAction". + + (* + pub fn is_call(&self) -> bool { + matches!(self, InterpreterAction::Call { .. }) + } + *) + Definition is_call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Call" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_call : M.IsAssociatedFunction Self "is_call" is_call. + + (* + pub fn is_create(&self) -> bool { + matches!(self, InterpreterAction::Create { .. }) + } + *) + Definition is_create (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Create" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_create : M.IsAssociatedFunction Self "is_create" is_create. + + (* + pub fn is_return(&self) -> bool { + matches!(self, InterpreterAction::Return { .. }) + } + *) + Definition is_return (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Return" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_return : M.IsAssociatedFunction Self "is_return" is_return. + + (* + pub fn is_none(&self) -> bool { + matches!(self, InterpreterAction::None) + } + *) + Definition is_none (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::None" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_none : M.IsAssociatedFunction Self "is_none" is_none. + + (* + pub fn is_some(&self) -> bool { + !self.is_none() + } + *) + Definition is_some (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::InterpreterAction", + "is_none", + [] + |), + [ M.read (| self |) ] + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_some : M.IsAssociatedFunction Self "is_some" is_some. + + (* + pub fn into_result_return(self) -> Option { + match self { + InterpreterAction::Return { result } => Some(result), + _ => None, + } + } + *) + Definition into_result_return (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Return", + "result" + |) in + let result := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| result |) ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_result_return : + M.IsAssociatedFunction Self "into_result_return" into_result_return. + End Impl_revm_interpreter_interpreter_action_InterpreterAction. +End interpreter_action. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/call_inputs.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/call_inputs.md new file mode 100644 index 00000000..fc6a9e6d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/call_inputs.md @@ -0,0 +1,2248 @@ +# ๐Ÿ“ call_inputs.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter_action/call_inputs.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter_action. + Module call_inputs. + (* StructRecord + { + name := "CallInputs"; + ty_params := []; + fields := + [ + ("input", Ty.path "alloy_primitives::bytes_::Bytes"); + ("return_memory_offset", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ]); + ("gas_limit", Ty.path "u64"); + ("bytecode_address", Ty.path "alloy_primitives::bits::address::Address"); + ("target_address", Ty.path "alloy_primitives::bits::address::Address"); + ("caller", Ty.path "alloy_primitives::bits::address::Address"); + ("value", Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue"); + ("scheme", Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme"); + ("is_static", Ty.path "bool"); + ("is_eof", Ty.path "bool") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::interpreter_action::call_inputs::CallInputs" + [ + ("input", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "input" + |) + ] + |)); + ("return_memory_offset", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "return_memory_offset" + |) + ] + |)); + ("gas_limit", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u64", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "gas_limit" + |) + ] + |)); + ("bytecode_address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "bytecode_address" + |) + ] + |)); + ("target_address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |) + ] + |)); + ("caller", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "caller" + |) + ] + |)); + ("value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |) + ] + |)); + ("scheme", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "scheme" + |) + ] + |)); + ("is_static", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "bool", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_static" + |) + ] + |)); + ("is_eof", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "bool", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_eof" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "input" |); + M.read (| Value.String "return_memory_offset" |); + M.read (| Value.String "gas_limit" |); + M.read (| Value.String "bytecode_address" |); + M.read (| Value.String "target_address" |); + M.read (| Value.String "caller" |); + M.read (| Value.String "value" |); + M.read (| Value.String "scheme" |); + M.read (| Value.String "is_static" |); + M.read (| Value.String "is_eof" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "input" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "return_memory_offset" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "gas_limit" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "bytecode_address" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "caller" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "scheme" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_static" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_eof" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CallInputs" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "input" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "input" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "return_memory_offset" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "return_memory_offset" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "gas_limit" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "gas_limit" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "bytecode_address" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "bytecode_address" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "caller" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "caller" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue", + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue" + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme", + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "scheme" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "scheme" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_static" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_static" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_eof" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_eof" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + + Module Impl_core_hash_Hash_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "input" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "return_memory_offset" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u64", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "gas_limit" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "bytecode_address" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "caller" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "scheme" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "bool", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_static" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "bool", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_eof" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_interpreter_action_call_inputs_CallInputs. + + Module Impl_revm_interpreter_interpreter_action_call_inputs_CallInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs". + + (* + pub fn new(tx_env: &TxEnv, gas_limit: u64) -> Option { + let TransactTo::Call(target_address) = tx_env.transact_to else { + return None; + }; + Some(CallInputs { + input: tx_env.data.clone(), + gas_limit, + target_address, + bytecode_address: target_address, + caller: tx_env.caller, + value: CallValue::Transfer(tx_env.value), + scheme: CallScheme::Call, + is_static: false, + is_eof: false, + return_memory_offset: 0..0, + }) + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ tx_env; gas_limit ] => + ltac:(M.monadic + (let tx_env := M.alloc (| tx_env |) in + let gas_limit := M.alloc (| gas_limit |) in + M.read (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| tx_env |), + "revm_primitives::env::TxEnv", + "transact_to" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + let target_address := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm_interpreter::interpreter_action::call_inputs::CallInputs" + [ + ("input", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| tx_env |), + "revm_primitives::env::TxEnv", + "data" + |) + ] + |)); + ("gas_limit", M.read (| gas_limit |)); + ("target_address", M.read (| target_address |)); + ("bytecode_address", M.read (| target_address |)); + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| tx_env |), + "revm_primitives::env::TxEnv", + "caller" + |) + |)); + ("value", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| tx_env |), + "revm_primitives::env::TxEnv", + "value" + |) + |) + ]); + ("scheme", + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallScheme::Call" + []); + ("is_static", Value.Bool false); + ("is_eof", Value.Bool false); + ("return_memory_offset", + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 0); ("end_", Value.Integer 0) ]) + ] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn new_boxed(tx_env: &TxEnv, gas_limit: u64) -> Option> { + Self::new(tx_env, gas_limit).map(Box::new) + } + *) + Definition new_boxed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ tx_env; gas_limit ] => + ltac:(M.monadic + (let tx_env := M.alloc (| tx_env |) in + let gas_limit := M.alloc (| gas_limit |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs" ], + "map", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.function + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs" ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "new", + [] + |), + [ M.read (| tx_env |); M.read (| gas_limit |) ] + |); + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_boxed : M.IsAssociatedFunction Self "new_boxed" new_boxed. + + (* + pub fn transfers_value(&self) -> bool { + self.value.transfer().is_some_and(|x| x > U256::ZERO) + } + *) + Definition transfers_value (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "is_some_and", + [ Ty.function [ Ty.tuple [ Ty.path "ruint::Uint" ] ] (Ty.path "bool") ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue", + "transfer", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let x := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "gt", + [] + |), + [ x; M.get_constant (| "ruint::ZERO" |) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transfers_value : + M.IsAssociatedFunction Self "transfers_value" transfers_value. + + (* + pub const fn transfer_value(&self) -> Option { + self.value.transfer() + } + *) + Definition transfer_value (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue", + "transfer", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transfer_value : + M.IsAssociatedFunction Self "transfer_value" transfer_value. + + (* + pub const fn apparent_value(&self) -> Option { + self.value.apparent() + } + *) + Definition apparent_value (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue", + "apparent", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_apparent_value : + M.IsAssociatedFunction Self "apparent_value" apparent_value. + + (* + pub const fn transfer_from(&self) -> Address { + self.caller + } + *) + Definition transfer_from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "caller" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transfer_from : + M.IsAssociatedFunction Self "transfer_from" transfer_from. + + (* + pub const fn transfer_to(&self) -> Address { + self.target_address + } + *) + Definition transfer_to (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transfer_to : M.IsAssociatedFunction Self "transfer_to" transfer_to. + + (* + pub const fn call_value(&self) -> U256 { + self.value.get() + } + *) + Definition call_value (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue", + "get", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_call_value : M.IsAssociatedFunction Self "call_value" call_value. + End Impl_revm_interpreter_interpreter_action_call_inputs_CallInputs. + + (* + Enum CallScheme + { + ty_params := []; + variants := + [ + { + name := "Call"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CallCode"; + item := StructTuple []; + discriminant := None; + }; + { + name := "DelegateCall"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StaticCall"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + + Module Impl_core_marker_Copy_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallScheme::Call" + |) in + M.alloc (| M.read (| Value.String "Call" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallScheme::CallCode" + |) in + M.alloc (| M.read (| Value.String "CallCode" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallScheme::DelegateCall" + |) in + M.alloc (| M.read (| Value.String "DelegateCall" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallScheme::StaticCall" + |) in + M.alloc (| M.read (| Value.String "StaticCall" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + + Module Impl_core_hash_Hash_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallScheme" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_interpreter_action_call_inputs_CallScheme. + + (* + Enum CallValue + { + ty_params := []; + variants := + [ + { + name := "Transfer"; + item := StructTuple [ Ty.path "ruint::Uint" ]; + discriminant := None; + }; + { + name := "Apparent"; + item := StructTuple [ Ty.path "ruint::Uint" ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Transfer" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Apparent" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::intrinsics::unreachable", [] |), + [] + |) + |) + |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + + Module Impl_core_hash_Hash_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "isize", + [], + "hash", + [ __H ] + |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + + Module Impl_core_default_Default_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue". + + (* + fn default() -> Self { + CallValue::Transfer(U256::ZERO) + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer" + [ M.read (| M.get_constant (| "ruint::ZERO" |) |) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_interpreter_action_call_inputs_CallValue. + + Module Impl_revm_interpreter_interpreter_action_call_inputs_CallValue. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallValue". + + (* + pub const fn get(&self) -> U256 { + match *self { + Self::Transfer(value) | Self::Apparent(value) => value, + } + } + *) + Definition get (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.read (| self |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + let value := M.copy (| ฮณ0_0 |) in + Value.Tuple [ value ])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent", + 0 + |) in + let value := M.copy (| ฮณ0_0 |) in + Value.Tuple [ value ])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with | [ value ] => value | _ => M.impossible (||) end)) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get : M.IsAssociatedFunction Self "get" get. + + (* + pub const fn transfer(&self) -> Option { + match *self { + Self::Transfer(transfer) => Some(transfer), + Self::Apparent(_) => None, + } + } + *) + Definition transfer (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.read (| self |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + let transfer := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| transfer |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent", + 0 + |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transfer : M.IsAssociatedFunction Self "transfer" transfer. + + (* + pub const fn is_transfer(&self) -> bool { + matches!(self, Self::Transfer(_)) + } + *) + Definition is_transfer (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_transfer : M.IsAssociatedFunction Self "is_transfer" is_transfer. + + (* + pub const fn apparent(&self) -> Option { + match *self { + Self::Transfer(_) => None, + Self::Apparent(apparent) => Some(apparent), + } + } + *) + Definition apparent (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.read (| self |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent", + 0 + |) in + let apparent := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| apparent |) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_apparent : M.IsAssociatedFunction Self "apparent" apparent. + + (* + pub const fn is_apparent(&self) -> bool { + matches!(self, Self::Apparent(_)) + } + *) + Definition is_apparent (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent", + 0 + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_apparent : M.IsAssociatedFunction Self "is_apparent" is_apparent. + End Impl_revm_interpreter_interpreter_action_call_inputs_CallValue. + End call_inputs. +End interpreter_action. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/call_outcome.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/call_outcome.md new file mode 100644 index 00000000..8c6c9613 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/call_outcome.md @@ -0,0 +1,420 @@ +# ๐Ÿ“ call_outcome.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter_action/call_outcome.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter_action. + Module call_outcome. + (* StructRecord + { + name := "CallOutcome"; + ty_params := []; + fields := + [ + ("result", Ty.path "revm_interpreter::interpreter::InterpreterResult"); + ("memory_offset", Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::interpreter_action::call_outcome::CallOutcome" + [ + ("result", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_interpreter::interpreter::InterpreterResult", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |) + ] + |)); + ("memory_offset", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "memory_offset" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CallOutcome" |); + M.read (| Value.String "result" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |)); + M.read (| Value.String "memory_offset" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "memory_offset" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::interpreter::InterpreterResult", + [ Ty.path "revm_interpreter::interpreter::InterpreterResult" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "memory_offset" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "memory_offset" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + + Module Impl_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome". + + (* + pub fn new(result: InterpreterResult, memory_offset: Range) -> Self { + Self { + result, + memory_offset, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ result; memory_offset ] => + ltac:(M.monadic + (let result := M.alloc (| result |) in + let memory_offset := M.alloc (| memory_offset |) in + Value.StructRecord + "revm_interpreter::interpreter_action::call_outcome::CallOutcome" + [ ("result", M.read (| result |)); ("memory_offset", M.read (| memory_offset |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn instruction_result(&self) -> &InstructionResult { + &self.result.result + } + *) + Definition instruction_result (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_instruction_result : + M.IsAssociatedFunction Self "instruction_result" instruction_result. + + (* + pub fn gas(&self) -> Gas { + self.result.gas + } + *) + Definition gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_gas : M.IsAssociatedFunction Self "gas" gas. + + (* + pub fn output(&self) -> &Bytes { + &self.result.output + } + *) + Definition output (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_output : M.IsAssociatedFunction Self "output" output. + + (* + pub fn memory_start(&self) -> usize { + self.memory_offset.start + } + *) + Definition memory_start (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "memory_offset" + |), + "core::ops::range::Range", + "start" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_memory_start : + M.IsAssociatedFunction Self "memory_start" memory_start. + + (* + pub fn memory_length(&self) -> usize { + self.memory_offset.len() + } + *) + Definition memory_length (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::exact_size::ExactSizeIterator", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "memory_offset" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_memory_length : + M.IsAssociatedFunction Self "memory_length" memory_length. + End Impl_revm_interpreter_interpreter_action_call_outcome_CallOutcome. + End call_outcome. +End interpreter_action. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/create_inputs.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/create_inputs.md new file mode 100644 index 00000000..7de36718 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/create_inputs.md @@ -0,0 +1,787 @@ +# ๐Ÿ“ create_inputs.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter_action/create_inputs.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter_action. + Module create_inputs. + (* StructRecord + { + name := "CreateInputs"; + ty_params := []; + fields := + [ + ("caller", Ty.path "alloy_primitives::bits::address::Address"); + ("scheme", Ty.path "revm_primitives::env::CreateScheme"); + ("value", Ty.path "ruint::Uint"); + ("init_code", Ty.path "alloy_primitives::bytes_::Bytes"); + ("gas_limit", Ty.path "u64") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::interpreter_action::create_inputs::CreateInputs" + [ + ("caller", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |) + ] + |)); + ("scheme", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::CreateScheme", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "scheme" + |) + ] + |)); + ("value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "value" + |) + ] + |)); + ("init_code", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "init_code" + |) + ] + |)); + ("gas_limit", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u64", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "gas_limit" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field5_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CreateInputs" |); + M.read (| Value.String "caller" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |)); + M.read (| Value.String "scheme" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "scheme" + |)); + M.read (| Value.String "value" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "value" + |)); + M.read (| Value.String "init_code" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "init_code" + |)); + M.read (| Value.String "gas_limit" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "gas_limit" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::CreateScheme", + [ Ty.path "revm_primitives::env::CreateScheme" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "scheme" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "scheme" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "value" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "init_code" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "init_code" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "gas_limit" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "gas_limit" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + + Module Impl_core_hash_Hash_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::env::CreateScheme", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "scheme" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "value" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "init_code" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u64", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "gas_limit" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + + Module Impl_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs". + + (* + pub fn new(tx_env: &TxEnv, gas_limit: u64) -> Option { + let TransactTo::Create = tx_env.transact_to else { + return None; + }; + + Some(CreateInputs { + caller: tx_env.caller, + scheme: CreateScheme::Create, + value: tx_env.value, + init_code: tx_env.data.clone(), + gas_limit, + }) + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ tx_env; gas_limit ] => + ltac:(M.monadic + (let tx_env := M.alloc (| tx_env |) in + let gas_limit := M.alloc (| gas_limit |) in + M.read (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| tx_env |), + "revm_primitives::env::TxEnv", + "transact_to" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::env::TransactTo::Create" |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm_interpreter::interpreter_action::create_inputs::CreateInputs" + [ + ("caller", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| tx_env |), + "revm_primitives::env::TxEnv", + "caller" + |) + |)); + ("scheme", + Value.StructTuple + "revm_primitives::env::CreateScheme::Create" + []); + ("value", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| tx_env |), + "revm_primitives::env::TxEnv", + "value" + |) + |)); + ("init_code", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| tx_env |), + "revm_primitives::env::TxEnv", + "data" + |) + ] + |)); + ("gas_limit", M.read (| gas_limit |)) + ] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn new_boxed(tx_env: &TxEnv, gas_limit: u64) -> Option> { + Self::new(tx_env, gas_limit).map(Box::new) + } + *) + Definition new_boxed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ tx_env; gas_limit ] => + ltac:(M.monadic + (let tx_env := M.alloc (| tx_env |) in + let gas_limit := M.alloc (| gas_limit |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs" ], + "map", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.function + [ Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs" ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "new", + [] + |), + [ M.read (| tx_env |); M.read (| gas_limit |) ] + |); + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_boxed : M.IsAssociatedFunction Self "new_boxed" new_boxed. + + (* + pub fn created_address(&self, nonce: u64) -> Address { + match self.scheme { + CreateScheme::Create => self.caller.create(nonce), + CreateScheme::Create2 { salt } => self + .caller + .create2_from_code(salt.to_be_bytes(), &self.init_code), + } + } + *) + Definition created_address (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; nonce ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let nonce := M.alloc (| nonce |) in + M.read (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "scheme" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::env::CreateScheme::Create" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "create", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |); + M.read (| nonce |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::env::CreateScheme::Create2", + "salt" + |) in + let salt := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "create2_from_code", + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "to_be_bytes", + [] + |), + [ salt ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "init_code" + |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_created_address : + M.IsAssociatedFunction Self "created_address" created_address. + End Impl_revm_interpreter_interpreter_action_create_inputs_CreateInputs. + End create_inputs. +End interpreter_action. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/create_outcome.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/create_outcome.md new file mode 100644 index 00000000..891778d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/create_outcome.md @@ -0,0 +1,367 @@ +# ๐Ÿ“ create_outcome.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter_action/create_outcome.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter_action. + Module create_outcome. + (* StructRecord + { + name := "CreateOutcome"; + ty_params := []; + fields := + [ + ("result", Ty.path "revm_interpreter::interpreter::InterpreterResult"); + ("address", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ]) + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_outcome::CreateOutcome". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CreateOutcome" |); + M.read (| Value.String "result" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |)); + M.read (| Value.String "address" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "address" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_outcome::CreateOutcome". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome" + [ + ("result", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_interpreter::interpreter::InterpreterResult", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |) + ] + |)); + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "address" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_outcome::CreateOutcome". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_outcome::CreateOutcome". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::interpreter::InterpreterResult", + [ Ty.path "revm_interpreter::interpreter::InterpreterResult" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "address" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "address" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_outcome::CreateOutcome". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_outcome::CreateOutcome". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + + Module Impl_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::create_outcome::CreateOutcome". + + (* + pub fn new(result: InterpreterResult, address: Option
) -> Self { + Self { result, address } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ result; address ] => + ltac:(M.monadic + (let result := M.alloc (| result |) in + let address := M.alloc (| address |) in + Value.StructRecord + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome" + [ ("result", M.read (| result |)); ("address", M.read (| address |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn instruction_result(&self) -> &InstructionResult { + &self.result.result + } + *) + Definition instruction_result (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_instruction_result : + M.IsAssociatedFunction Self "instruction_result" instruction_result. + + (* + pub fn output(&self) -> &Bytes { + &self.result.output + } + *) + Definition output (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_output : M.IsAssociatedFunction Self "output" output. + + (* + pub fn gas(&self) -> &Gas { + &self.result.gas + } + *) + Definition gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_gas : M.IsAssociatedFunction Self "gas" gas. + End Impl_revm_interpreter_interpreter_action_create_outcome_CreateOutcome. + End create_outcome. +End interpreter_action. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/eof_create_inputs.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/eof_create_inputs.md new file mode 100644 index 00000000..caf18d8a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/eof_create_inputs.md @@ -0,0 +1,635 @@ +# ๐Ÿ“ eof_create_inputs.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter_action/eof_create_inputs.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter_action. + Module eof_create_inputs. + (* StructRecord + { + name := "EOFCreateInput"; + ty_params := []; + fields := + [ + ("caller", Ty.path "alloy_primitives::bits::address::Address"); + ("created_address", Ty.path "alloy_primitives::bits::address::Address"); + ("value", Ty.path "ruint::Uint"); + ("eof_init_code", Ty.path "revm_primitives::bytecode::eof::Eof"); + ("gas_limit", Ty.path "u64"); + ("return_memory_range", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ]) + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "caller" |); + M.read (| Value.String "created_address" |); + M.read (| Value.String "value" |); + M.read (| Value.String "eof_init_code" |); + M.read (| Value.String "gas_limit" |); + M.read (| Value.String "return_memory_range" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "caller" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "created_address" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "value" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "eof_init_code" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "gas_limit" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "return_memory_range" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "EOFCreateInput" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + + Module Impl_core_default_Default_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput" + [ + ("caller", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bits::address::Address", + [], + "default", + [] + |), + [] + |)); + ("created_address", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bits::address::Address", + [], + "default", + [] + |), + [] + |)); + ("value", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "ruint::Uint", + [], + "default", + [] + |), + [] + |)); + ("eof_init_code", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::eof::Eof", + [], + "default", + [] + |), + [] + |)); + ("gas_limit", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u64", + [], + "default", + [] + |), + [] + |)); + ("return_memory_range", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput" + [ + ("caller", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "caller" + |) + ] + |)); + ("created_address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "created_address" + |) + ] + |)); + ("value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "value" + |) + ] + |)); + ("eof_init_code", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::eof::Eof", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "eof_init_code" + |) + ] + |)); + ("gas_limit", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u64", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "gas_limit" + |) + ] + |)); + ("return_memory_range", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "return_memory_range" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "caller" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "caller" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "created_address" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "created_address" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "value" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::bytecode::eof::Eof", + [ Ty.path "revm_primitives::bytecode::eof::Eof" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "eof_init_code" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "eof_init_code" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "gas_limit" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "gas_limit" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "return_memory_range" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "return_memory_range" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + + Module Impl_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput". + + (* + pub fn new( + caller: Address, + created_address: Address, + value: U256, + eof_init_code: Eof, + gas_limit: u64, + return_memory_range: Range, + ) -> EOFCreateInput { + EOFCreateInput { + caller, + created_address, + value, + eof_init_code, + gas_limit, + return_memory_range, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ caller; created_address; value; eof_init_code; gas_limit; return_memory_range ] => + ltac:(M.monadic + (let caller := M.alloc (| caller |) in + let created_address := M.alloc (| created_address |) in + let value := M.alloc (| value |) in + let eof_init_code := M.alloc (| eof_init_code |) in + let gas_limit := M.alloc (| gas_limit |) in + let return_memory_range := M.alloc (| return_memory_range |) in + Value.StructRecord + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput" + [ + ("caller", M.read (| caller |)); + ("created_address", M.read (| created_address |)); + ("value", M.read (| value |)); + ("eof_init_code", M.read (| eof_init_code |)); + ("gas_limit", M.read (| gas_limit |)); + ("return_memory_range", M.read (| return_memory_range |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + End Impl_revm_interpreter_interpreter_action_eof_create_inputs_EOFCreateInput. + End eof_create_inputs. +End interpreter_action. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/eof_create_outcome.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/eof_create_outcome.md new file mode 100644 index 00000000..cb6329fa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/interpreter_action/eof_create_outcome.md @@ -0,0 +1,459 @@ +# ๐Ÿ“ eof_create_outcome.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/interpreter_action/eof_create_outcome.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module interpreter_action. + Module eof_create_outcome. + (* StructRecord + { + name := "EOFCreateOutcome"; + ty_params := []; + fields := + [ + ("result", Ty.path "revm_interpreter::interpreter::InterpreterResult"); + ("address", Ty.path "alloy_primitives::bits::address::Address"); + ("return_memory_range", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ]) + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "EOFCreateOutcome" |); + M.read (| Value.String "result" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |)); + M.read (| Value.String "address" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "address" + |)); + M.read (| Value.String "return_memory_range" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "return_memory_range" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + + Module Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome" + [ + ("result", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_interpreter::interpreter::InterpreterResult", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |) + ] + |)); + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "address" + |) + ] + |)); + ("return_memory_range", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "return_memory_range" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_interpreter::interpreter::InterpreterResult", + [ Ty.path "revm_interpreter::interpreter::InterpreterResult" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "address" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "address" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "return_memory_range" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "return_memory_range" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + + Module Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + + Module Impl_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + Definition Self : Ty.t := + Ty.path "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome". + + (* + pub fn new( + result: InterpreterResult, + address: Address, + return_memory_range: Range, + ) -> Self { + Self { + result, + address, + return_memory_range, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ result; address; return_memory_range ] => + ltac:(M.monadic + (let result := M.alloc (| result |) in + let address := M.alloc (| address |) in + let return_memory_range := M.alloc (| return_memory_range |) in + Value.StructRecord + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome" + [ + ("result", M.read (| result |)); + ("address", M.read (| address |)); + ("return_memory_range", M.read (| return_memory_range |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn instruction_result(&self) -> &InstructionResult { + &self.result.result + } + *) + Definition instruction_result (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_instruction_result : + M.IsAssociatedFunction Self "instruction_result" instruction_result. + + (* + pub fn output(&self) -> &Bytes { + &self.result.output + } + *) + Definition output (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_output : M.IsAssociatedFunction Self "output" output. + + (* + pub fn gas(&self) -> &Gas { + &self.result.gas + } + *) + Definition gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_gas : M.IsAssociatedFunction Self "gas" gas. + + (* + pub fn return_range(&self) -> Range { + self.return_memory_range.clone() + } + *) + Definition return_range (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "return_memory_range" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_return_range : + M.IsAssociatedFunction Self "return_range" return_range. + End Impl_revm_interpreter_interpreter_action_eof_create_outcome_EOFCreateOutcome. + End eof_create_outcome. +End interpreter_action. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/opcode.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/opcode.md new file mode 100644 index 00000000..6093032f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/opcode.md @@ -0,0 +1,21275 @@ +# ๐Ÿ“ opcode.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/opcode.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module opcode. + Axiom Instruction : + forall (H : Ty.t), + (Ty.apply (Ty.path "revm_interpreter::opcode::Instruction") [ H ]) = + (Ty.function + [ + Ty.apply (Ty.path "&mut") [ Ty.path "revm_interpreter::interpreter::Interpreter" ]; + Ty.apply (Ty.path "&mut") [ H ] + ] + (Ty.tuple [])). + + Axiom InstructionTable : + forall (H : Ty.t), + (Ty.apply (Ty.path "revm_interpreter::opcode::InstructionTable") [ H ]) = + (Ty.apply + (Ty.path "array") + [ + Ty.function + [ + Ty.apply (Ty.path "&mut") [ Ty.path "revm_interpreter::interpreter::Interpreter" ]; + Ty.apply (Ty.path "&mut") [ H ] + ] + (Ty.tuple []) + ]). + + Axiom BoxedInstruction : + forall (H : Ty.t), + (Ty.apply (Ty.path "revm_interpreter::opcode::BoxedInstruction") [ H ]) = + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom BoxedInstructionTable : + forall (H : Ty.t), + (Ty.apply (Ty.path "revm_interpreter::opcode::BoxedInstructionTable") [ H ]) = + (Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ]). + + (* + Enum InstructionTables + { + ty_params := [ "H" ]; + variants := + [ + { + name := "Plain"; + item := + StructTuple + [ + Ty.apply + (Ty.path "array") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::Interpreter" ]; + Ty.apply (Ty.path "&mut") [ H ] + ] + (Ty.tuple []) + ] + ]; + discriminant := None; + }; + { + name := "Boxed"; + item := + StructTuple + [ + Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ] + ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_revm_interpreter_opcode_InstructionTables_H. + Definition Self (H : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_interpreter::opcode::InstructionTables") [ H ]. + + (* + pub const fn new_plain() -> Self { + Self::Plain(make_instruction_table::()) + } + *) + Definition new_plain (H : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self H in + match ฯ„, ฮฑ with + | [ SPEC ], [] => + ltac:(M.monadic + (Value.StructTuple + "revm_interpreter::opcode::InstructionTables::Plain" + [ + M.call_closure (| + M.get_function (| + "revm_interpreter::opcode::make_instruction_table", + [ H; SPEC ] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_plain : + forall (H : Ty.t), + M.IsAssociatedFunction (Self H) "new_plain" (new_plain H). + (* + pub fn insert_boxed(&mut self, opcode: u8, instruction: BoxedInstruction<'a, H>) { + // first convert the table to boxed variant + self.convert_boxed(); + + // now we can insert the instruction + match self { + Self::Plain(_) => { + unreachable!("we already converted the table to boxed variant"); + } + Self::Boxed(table) => { + table[opcode as usize] = Box::new(instruction); + } + } + } + *) + Definition insert_boxed (H : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self H in + match ฯ„, ฮฑ with + | [], [ self; opcode; instruction ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let opcode := M.alloc (| opcode |) in + let instruction := M.alloc (| instruction |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm_interpreter::opcode::InstructionTables") [ H ], + "convert_boxed", + [] + |), + [ M.read (| self |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Plain", + 0 + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: we already converted the table to boxed variant" + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "none", + [] + |), + [] + |) + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Boxed", + 0 + |) in + let table := M.alloc (| ฮณ1_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| + M.read (| table |), + M.alloc (| M.rust_cast (M.read (| opcode |)) |) + |), + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| instruction |) ] + |)) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_boxed : + forall (H : Ty.t), + M.IsAssociatedFunction (Self H) "insert_boxed" (insert_boxed H). + + (* + pub fn insert(&mut self, opcode: u8, instruction: Instruction) { + match self { + Self::Plain(table) => { + table[opcode as usize] = instruction; + } + Self::Boxed(table) => { + table[opcode as usize] = Box::new(instruction); + } + } + } + *) + Definition insert (H : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self H in + match ฯ„, ฮฑ with + | [], [ self; opcode; instruction ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let opcode := M.alloc (| opcode |) in + let instruction := M.alloc (| instruction |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Plain", + 0 + |) in + let table := M.alloc (| ฮณ1_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| + M.read (| table |), + M.alloc (| M.rust_cast (M.read (| opcode |)) |) + |), + M.read (| instruction |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Boxed", + 0 + |) in + let table := M.alloc (| ฮณ1_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| + M.read (| table |), + M.alloc (| M.rust_cast (M.read (| opcode |)) |) + |), + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::Interpreter" ]; + Ty.apply (Ty.path "&mut") [ H ] + ] + (Ty.tuple []); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| instruction |) ] + |)) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert : + forall (H : Ty.t), + M.IsAssociatedFunction (Self H) "insert" (insert H). + + (* + pub fn convert_boxed(&mut self) { + match self { + Self::Plain(table) => { + *self = Self::Boxed(core::array::from_fn(|i| { + let instruction: BoxedInstruction<'a, H> = Box::new(table[i]); + instruction + })); + } + Self::Boxed(_) => {} + }; + } + *) + Definition convert_boxed (H : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self H in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Plain", + 0 + |) in + let table := M.alloc (| ฮณ1_0 |) in + let~ _ := + M.write (| + M.read (| self |), + Value.StructTuple + "revm_interpreter::opcode::InstructionTables::Boxed" + [ + M.call_closure (| + M.get_function (| + "core::array::from_fn", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.function + [ Ty.tuple [ Ty.path "usize" ] ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let i := M.copy (| ฮณ |) in + (* Unsize *) + M.pointer_coercion + (M.read (| + let~ instruction := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ H ] + ] + (Ty.tuple []); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| table |), + i + |) + |) + ] + |)) + |) in + instruction + |)))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Boxed", + 0 + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_convert_boxed : + forall (H : Ty.t), + M.IsAssociatedFunction (Self H) "convert_boxed" (convert_boxed H). + End Impl_revm_interpreter_opcode_InstructionTables_H. + + + (* + pub const fn make_instruction_table() -> InstructionTable { + // Force const-eval of the table creation, making this function trivial. + // TODO: Replace this with a `const {}` block once it is stable. + struct ConstTable { + _host: core::marker::PhantomData, + _spec: core::marker::PhantomData, + } + impl ConstTable { + const NEW: InstructionTable = { + let mut tables: InstructionTable = [control::unknown; 256]; + let mut i = 0; + while i < 256 { + tables[i] = instruction::(i as u8); + i += 1; + } + tables + }; + } + ConstTable::::NEW + } + *) + Definition make_instruction_table (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [] => + ltac:(M.monadic + (M.read (| M.get_constant (| "revm_interpreter::opcode::make_instruction_table::NEW" |) |))) + | _, _ => M.impossible + end. + + Axiom Function_make_instruction_table : + M.IsFunction "revm_interpreter::opcode::make_instruction_table" make_instruction_table. + + Module make_instruction_table. + (* StructRecord + { + name := "ConstTable"; + ty_params := [ "H"; "SPEC" ]; + fields := + [ + ("_host", Ty.apply (Ty.path "core::marker::PhantomData") [ H ]); + ("_spec", Ty.apply (Ty.path "core::marker::PhantomData") [ SPEC ]) + ]; + } *) + + Module Impl_revm_interpreter_opcode_make_instruction_table_ConstTable_H_SPEC. + Definition Self (H SPEC : Ty.t) : Ty.t := + Ty.apply + (Ty.path "revm_interpreter::opcode::make_instruction_table::ConstTable") + [ H; SPEC ]. + + (* + const NEW: InstructionTable = { + let mut tables: InstructionTable = [control::unknown; 256]; + let mut i = 0; + while i < 256 { + tables[i] = instruction::(i as u8); + i += 1; + } + tables + }; + *) + (* Ty.apply + (Ty.path "array") + [ + Ty.function + [ + Ty.apply (Ty.path "&mut") [ Ty.path "revm_interpreter::interpreter::Interpreter" ]; + Ty.apply (Ty.path "&mut") [ H ] + ] + (Ty.tuple []) + ] *) + Definition value_NEW (H SPEC : Ty.t) : Value.t := + let Self : Ty.t := Self H SPEC in + M.run + ltac:(M.monadic + (let~ tables := + M.alloc (| + repeat + (* ReifyFnPointer *) + (M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::control::unknown", + [ H ] + |))) + 256 + |) in + let~ i := M.alloc (| Value.Integer 0 |) in + let~ _ := + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| BinOp.Pure.lt (M.read (| i |)) (Value.Integer 256) |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| tables, i |), + M.call_closure (| + M.get_function (| + "revm_interpreter::opcode::instruction", + [ H; SPEC ] + |), + [ M.rust_cast (M.read (| i |)) ] + |) + |) in + let~ _ := + let ฮฒ := i in + M.write (| + ฮฒ, + BinOp.Wrap.add Integer.Usize (M.read (| ฮฒ |)) (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| M.never_to_any (| M.read (| M.break (||) |) |) |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) in + tables)). + + Axiom AssociatedConstant_value_NEW : + forall (H SPEC : Ty.t), + M.IsAssociatedConstant (Self H SPEC) "value_NEW" (value_NEW H SPEC). + End Impl_revm_interpreter_opcode_make_instruction_table_ConstTable_H_SPEC. + End make_instruction_table. + + (* + pub fn make_boxed_instruction_table<'a, H, SPEC, FN>( + table: InstructionTable, + mut outer: FN, + ) -> BoxedInstructionTable<'a, H> + where + H: Host, + SPEC: Spec + 'a, + FN: FnMut(Instruction) -> BoxedInstruction<'a, H>, + { + core::array::from_fn(|i| outer(table[i])) + } + *) + Definition make_boxed_instruction_table (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC; FN ], [ table; outer ] => + ltac:(M.monadic + (let table := M.alloc (| table |) in + let outer := M.alloc (| outer |) in + M.call_closure (| + M.get_function (| + "core::array::from_fn", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.function + [ Ty.tuple [ Ty.path "usize" ] ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let i := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnMut", + FN, + [ + Ty.tuple + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply (Ty.path "&mut") [ H ] + ] + (Ty.tuple []) + ] + ], + "call_mut", + [] + |), + [ + outer; + Value.Tuple + [ M.read (| M.SubPointer.get_array_field (| table, i |) |) ] + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_make_boxed_instruction_table : + M.IsFunction + "revm_interpreter::opcode::make_boxed_instruction_table" + make_boxed_instruction_table. + + (* StructTuple + { + name := "OpCodeError"; + ty_params := []; + fields := [ Ty.tuple [] ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_interpreter_opcode_OpCodeError. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeError". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "OpCodeError" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeError", + 0 + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_opcode_OpCodeError. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_opcode_OpCodeError. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_opcode_OpCodeError. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_opcode_OpCodeError. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeError". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| "core::cmp::PartialEq", Ty.tuple [], [ Ty.tuple [] ], "eq", [] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeError", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeError", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_opcode_OpCodeError. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_opcode_OpCodeError. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_opcode_OpCodeError. + + Module Impl_core_cmp_Eq_for_revm_interpreter_opcode_OpCodeError. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeError". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_opcode_OpCodeError. + + Module Impl_core_fmt_Display_for_revm_interpreter_opcode_OpCodeError. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeError". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("invalid opcode") + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "invalid opcode" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Display" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Display_for_revm_interpreter_opcode_OpCodeError. + + Module Impl_core_error_Error_for_revm_interpreter_opcode_OpCodeError. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeError". + + Axiom Implements : + M.IsTraitInstance + "core::error::Error" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_error_Error_for_revm_interpreter_opcode_OpCodeError. + + (* StructTuple + { + name := "OpCode"; + ty_params := []; + fields := [ Ty.path "u8" ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_marker_Copy_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_fmt_Debug_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "OpCode" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCode", + 0 + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_default_Default_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm_interpreter::opcode::OpCode" + [ + M.call_closure (| + M.get_trait_method (| "core::default::Default", Ty.path "u8", [], "default", [] |), + [] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCode", + 0 + |) + |)) + (M.read (| + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCode", + 0 + |) + |)))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_cmp_Eq_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_cmp_PartialOrd_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "u8", + [ Ty.path "u8" ], + "partial_cmp", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCode", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCode", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_cmp_Ord_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "u8", [], "cmp", [] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCode", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCode", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_hash_Hash_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u8", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCode", + 0 + |); + M.read (| state |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_fmt_Display_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let n = self.get(); + if let Some(val) = OPCODE_INFO_JUMPTABLE[n as usize] { + f.write_str(val.name()) + } else { + write!(f, "UNKNOWN(0x{n:02X})") + } + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ n := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "get", + [] + |), + [ M.read (| M.read (| self |) |) ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.SubPointer.get_array_field (| + M.get_constant (| "revm_interpreter::opcode::OPCODE_INFO_JUMPTABLE" |), + M.alloc (| M.rust_cast (M.read (| n |)) |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "name", + [] + |), + [ val ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1_formatted", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| Value.String "UNKNOWN(0x" |); + M.read (| Value.String ")" |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_upper_hex", + [ Ty.path "u8" ] + |), + [ n ] + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 0; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 8; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple + "core::fmt::rt::Count::Is" + [ Value.Integer 2 ] + ] + |) + ] + |)); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::UnsafeArg", + "new", + [] + |), + [] + |) + ] + |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Display" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Display_for_revm_interpreter_opcode_OpCode. + + Module Impl_core_str_traits_FromStr_for_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* type Err = OpCodeError; *) + Definition _Err : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeError". + + (* + fn from_str(s: &str) -> Result { + Self::parse(s).ok_or(OpCodeError(())) + } + *) + Definition from_str (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ s ] => + ltac:(M.monadic + (let s := M.alloc (| s |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_interpreter::opcode::OpCode" ], + "ok_or", + [ Ty.path "revm_interpreter::opcode::OpCodeError" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "parse", + [] + |), + [ M.read (| s |) ] + |); + Value.StructTuple "revm_interpreter::opcode::OpCodeError" [ Value.Tuple [] ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::str::traits::FromStr" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("Err", InstanceField.Ty _Err); ("from_str", InstanceField.Method from_str) ]. + End Impl_core_str_traits_FromStr_for_revm_interpreter_opcode_OpCode. + + Module Impl_revm_interpreter_opcode_OpCode. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCode". + + (* + pub const fn new(opcode: u8) -> Option { + match OPCODE_INFO_JUMPTABLE[opcode as usize] { + Some(_) => Some(Self(opcode)), + None => None, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ opcode ] => + ltac:(M.monadic + (let opcode := M.alloc (| opcode |) in + M.read (| + M.match_operator (| + M.SubPointer.get_array_field (| + M.get_constant (| "revm_interpreter::opcode::OPCODE_INFO_JUMPTABLE" |), + M.alloc (| M.rust_cast (M.read (| opcode |)) |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm_interpreter::opcode::OpCode" + [ M.read (| opcode |) ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn parse(s: &str) -> Option { + NAME_TO_OPCODE.get(s).copied() + } + *) + Definition parse (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ s ] => + ltac:(M.monadic + (let s := M.alloc (| s |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_interpreter::opcode::OpCode" ] ], + "copied", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "phf::map::Map") + [ + Ty.apply (Ty.path "&") [ Ty.path "str" ]; + Ty.path "revm_interpreter::opcode::OpCode" + ], + "get", + [ Ty.path "str" ] + |), + [ + M.read (| M.get_constant (| "revm_interpreter::opcode::NAME_TO_OPCODE" |) |); + M.read (| s |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_parse : M.IsAssociatedFunction Self "parse" parse. + + (* + pub const fn is_jumpdest(&self) -> bool { + self.0 == JUMPDEST + } + *) + Definition is_jumpdest (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCode", + 0 + |) + |)) + (M.read (| M.get_constant (| "revm_interpreter::opcode::JUMPDEST" |) |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_jumpdest : M.IsAssociatedFunction Self "is_jumpdest" is_jumpdest. + + (* + pub const fn is_jumpdest_by_op(opcode: u8) -> bool { + if let Some(opcode) = Self::new(opcode) { + opcode.is_jumpdest() + } else { + false + } + } + *) + Definition is_jumpdest_by_op (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ opcode ] => + ltac:(M.monadic + (let opcode := M.alloc (| opcode |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "new", + [] + |), + [ M.read (| opcode |) ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let opcode := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "is_jumpdest", + [] + |), + [ opcode ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_jumpdest_by_op : + M.IsAssociatedFunction Self "is_jumpdest_by_op" is_jumpdest_by_op. + + (* + pub const fn is_jump(self) -> bool { + self.0 == JUMP + } + *) + Definition is_jump (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_tuple_field (| self, "revm_interpreter::opcode::OpCode", 0 |) + |)) + (M.read (| M.get_constant (| "revm_interpreter::opcode::JUMP" |) |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_jump : M.IsAssociatedFunction Self "is_jump" is_jump. + + (* + pub const fn is_jump_by_op(opcode: u8) -> bool { + if let Some(opcode) = Self::new(opcode) { + opcode.is_jump() + } else { + false + } + } + *) + Definition is_jump_by_op (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ opcode ] => + ltac:(M.monadic + (let opcode := M.alloc (| opcode |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "new", + [] + |), + [ M.read (| opcode |) ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let opcode := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "is_jump", + [] + |), + [ M.read (| opcode |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_jump_by_op : + M.IsAssociatedFunction Self "is_jump_by_op" is_jump_by_op. + + (* + pub const fn is_push(self) -> bool { + self.0 >= PUSH1 && self.0 <= PUSH32 + } + *) + Definition is_push (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + LogicalOp.and (| + BinOp.Pure.ge + (M.read (| + M.SubPointer.get_struct_tuple_field (| + self, + "revm_interpreter::opcode::OpCode", + 0 + |) + |)) + (M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH1" |) |)), + ltac:(M.monadic + (BinOp.Pure.le + (M.read (| + M.SubPointer.get_struct_tuple_field (| + self, + "revm_interpreter::opcode::OpCode", + 0 + |) + |)) + (M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH32" |) |)))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_push : M.IsAssociatedFunction Self "is_push" is_push. + + (* + pub fn is_push_by_op(opcode: u8) -> bool { + if let Some(opcode) = Self::new(opcode) { + opcode.is_push() + } else { + false + } + } + *) + Definition is_push_by_op (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ opcode ] => + ltac:(M.monadic + (let opcode := M.alloc (| opcode |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "new", + [] + |), + [ M.read (| opcode |) ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let opcode := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "is_push", + [] + |), + [ M.read (| opcode |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_push_by_op : + M.IsAssociatedFunction Self "is_push_by_op" is_push_by_op. + + (* + pub unsafe fn new_unchecked(opcode: u8) -> Self { + Self(opcode) + } + *) + Definition new_unchecked (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ opcode ] => + ltac:(M.monadic + (let opcode := M.alloc (| opcode |) in + Value.StructTuple "revm_interpreter::opcode::OpCode" [ M.read (| opcode |) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_unchecked : + M.IsAssociatedFunction Self "new_unchecked" new_unchecked. + + (* + pub const fn as_str(self) -> &'static str { + self.info().name() + } + *) + Definition as_str (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "name", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "info", + [] + |), + [ self ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_as_str : M.IsAssociatedFunction Self "as_str" as_str. + + (* + pub const fn name_by_op(opcode: u8) -> &'static str { + if let Some(opcode) = Self::new(opcode) { + opcode.as_str() + } else { + "Unknown" + } + } + *) + Definition name_by_op (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ opcode ] => + ltac:(M.monadic + (let opcode := M.alloc (| opcode |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "new", + [] + |), + [ M.read (| opcode |) ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let opcode := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "as_str", + [] + |), + [ M.read (| opcode |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (Value.String "Unknown")) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_name_by_op : M.IsAssociatedFunction Self "name_by_op" name_by_op. + + (* + pub const fn inputs(&self) -> u8 { + self.info().inputs() + } + *) + Definition inputs (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "inputs", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "info", + [] + |), + [ M.read (| self |) ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_inputs : M.IsAssociatedFunction Self "inputs" inputs. + + (* + pub const fn outputs(&self) -> u8 { + self.info().outputs() + } + *) + Definition outputs (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "outputs", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "info", + [] + |), + [ M.read (| self |) ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_outputs : M.IsAssociatedFunction Self "outputs" outputs. + + (* + pub const fn io_diff(&self) -> i16 { + self.info().io_diff() + } + *) + Definition io_diff (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "io_diff", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "info", + [] + |), + [ M.read (| self |) ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_io_diff : M.IsAssociatedFunction Self "io_diff" io_diff. + + (* + pub const fn info_by_op(opcode: u8) -> Option { + if let Some(opcode) = Self::new(opcode) { + Some(opcode.info()) + } else { + None + } + } + *) + Definition info_by_op (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ opcode ] => + ltac:(M.monadic + (let opcode := M.alloc (| opcode |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "new", + [] + |), + [ M.read (| opcode |) ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let opcode := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "info", + [] + |), + [ opcode ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_info_by_op : M.IsAssociatedFunction Self "info_by_op" info_by_op. + + (* + pub const fn info(&self) -> OpCodeInfo { + if let Some(t) = OPCODE_INFO_JUMPTABLE[self.0 as usize] { + t + } else { + panic!("opcode not found") + } + } + *) + Definition info (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.SubPointer.get_array_field (| + M.get_constant (| "revm_interpreter::opcode::OPCODE_INFO_JUMPTABLE" |), + M.alloc (| + M.rust_cast + (M.read (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCode", + 0 + |) + |)) + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let t := M.copy (| ฮณ0_0 |) in + t)); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array [ M.read (| Value.String "opcode not found" |) ] + |)) + ] + |) + ] + |) + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_info : M.IsAssociatedFunction Self "info" info. + + (* + pub const fn input_output(&self) -> (u8, u8) { + let info = self.info(); + (info.inputs, info.outputs) + } + *) + Definition input_output (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "info", + [] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + Value.Tuple + [ + M.read (| + M.SubPointer.get_struct_record_field (| + info, + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + info, + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |) + |) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_input_output : M.IsAssociatedFunction Self "input_output" input_output. + + (* + pub const fn get(self) -> u8 { + self.0 + } + *) + Definition get (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_tuple_field (| self, "revm_interpreter::opcode::OpCode", 0 |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get : M.IsAssociatedFunction Self "get" get. + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_STOP : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 0 ] |))). + + Axiom AssociatedConstant_value_STOP : M.IsAssociatedConstant Self "value_STOP" value_STOP. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_ADD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 1 ] |))). + + Axiom AssociatedConstant_value_ADD : M.IsAssociatedConstant Self "value_ADD" value_ADD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_MUL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 2 ] |))). + + Axiom AssociatedConstant_value_MUL : M.IsAssociatedConstant Self "value_MUL" value_MUL. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SUB : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 3 ] |))). + + Axiom AssociatedConstant_value_SUB : M.IsAssociatedConstant Self "value_SUB" value_SUB. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DIV : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 4 ] |))). + + Axiom AssociatedConstant_value_DIV : M.IsAssociatedConstant Self "value_DIV" value_DIV. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SDIV : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 5 ] |))). + + Axiom AssociatedConstant_value_SDIV : M.IsAssociatedConstant Self "value_SDIV" value_SDIV. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_MOD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 6 ] |))). + + Axiom AssociatedConstant_value_MOD : M.IsAssociatedConstant Self "value_MOD" value_MOD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SMOD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 7 ] |))). + + Axiom AssociatedConstant_value_SMOD : M.IsAssociatedConstant Self "value_SMOD" value_SMOD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_ADDMOD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 8 ] |))). + + Axiom AssociatedConstant_value_ADDMOD : M.IsAssociatedConstant Self "value_ADDMOD" value_ADDMOD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_MULMOD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 9 ] |))). + + Axiom AssociatedConstant_value_MULMOD : M.IsAssociatedConstant Self "value_MULMOD" value_MULMOD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EXP : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 10 ] + |))). + + Axiom AssociatedConstant_value_EXP : M.IsAssociatedConstant Self "value_EXP" value_EXP. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SIGNEXTEND : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 11 ] + |))). + + Axiom AssociatedConstant_value_SIGNEXTEND : + M.IsAssociatedConstant Self "value_SIGNEXTEND" value_SIGNEXTEND. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_LT : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 16 ] + |))). + + Axiom AssociatedConstant_value_LT : M.IsAssociatedConstant Self "value_LT" value_LT. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_GT : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 17 ] + |))). + + Axiom AssociatedConstant_value_GT : M.IsAssociatedConstant Self "value_GT" value_GT. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SLT : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 18 ] + |))). + + Axiom AssociatedConstant_value_SLT : M.IsAssociatedConstant Self "value_SLT" value_SLT. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SGT : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 19 ] + |))). + + Axiom AssociatedConstant_value_SGT : M.IsAssociatedConstant Self "value_SGT" value_SGT. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EQ : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 20 ] + |))). + + Axiom AssociatedConstant_value_EQ : M.IsAssociatedConstant Self "value_EQ" value_EQ. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_ISZERO : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 21 ] + |))). + + Axiom AssociatedConstant_value_ISZERO : M.IsAssociatedConstant Self "value_ISZERO" value_ISZERO. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_AND : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 22 ] + |))). + + Axiom AssociatedConstant_value_AND : M.IsAssociatedConstant Self "value_AND" value_AND. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_OR : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 23 ] + |))). + + Axiom AssociatedConstant_value_OR : M.IsAssociatedConstant Self "value_OR" value_OR. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_XOR : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 24 ] + |))). + + Axiom AssociatedConstant_value_XOR : M.IsAssociatedConstant Self "value_XOR" value_XOR. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_NOT : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 25 ] + |))). + + Axiom AssociatedConstant_value_NOT : M.IsAssociatedConstant Self "value_NOT" value_NOT. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_BYTE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 26 ] + |))). + + Axiom AssociatedConstant_value_BYTE : M.IsAssociatedConstant Self "value_BYTE" value_BYTE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SHL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 27 ] + |))). + + Axiom AssociatedConstant_value_SHL : M.IsAssociatedConstant Self "value_SHL" value_SHL. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SHR : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 28 ] + |))). + + Axiom AssociatedConstant_value_SHR : M.IsAssociatedConstant Self "value_SHR" value_SHR. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SAR : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 29 ] + |))). + + Axiom AssociatedConstant_value_SAR : M.IsAssociatedConstant Self "value_SAR" value_SAR. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_KECCAK256 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 32 ] + |))). + + Axiom AssociatedConstant_value_KECCAK256 : + M.IsAssociatedConstant Self "value_KECCAK256" value_KECCAK256. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_ADDRESS : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 48 ] + |))). + + Axiom AssociatedConstant_value_ADDRESS : + M.IsAssociatedConstant Self "value_ADDRESS" value_ADDRESS. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_BALANCE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 49 ] + |))). + + Axiom AssociatedConstant_value_BALANCE : + M.IsAssociatedConstant Self "value_BALANCE" value_BALANCE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_ORIGIN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 50 ] + |))). + + Axiom AssociatedConstant_value_ORIGIN : M.IsAssociatedConstant Self "value_ORIGIN" value_ORIGIN. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CALLER : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 51 ] + |))). + + Axiom AssociatedConstant_value_CALLER : M.IsAssociatedConstant Self "value_CALLER" value_CALLER. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CALLVALUE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 52 ] + |))). + + Axiom AssociatedConstant_value_CALLVALUE : + M.IsAssociatedConstant Self "value_CALLVALUE" value_CALLVALUE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CALLDATALOAD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 53 ] + |))). + + Axiom AssociatedConstant_value_CALLDATALOAD : + M.IsAssociatedConstant Self "value_CALLDATALOAD" value_CALLDATALOAD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CALLDATASIZE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 54 ] + |))). + + Axiom AssociatedConstant_value_CALLDATASIZE : + M.IsAssociatedConstant Self "value_CALLDATASIZE" value_CALLDATASIZE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CALLDATACOPY : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 55 ] + |))). + + Axiom AssociatedConstant_value_CALLDATACOPY : + M.IsAssociatedConstant Self "value_CALLDATACOPY" value_CALLDATACOPY. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CODESIZE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 56 ] + |))). + + Axiom AssociatedConstant_value_CODESIZE : + M.IsAssociatedConstant Self "value_CODESIZE" value_CODESIZE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CODECOPY : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 57 ] + |))). + + Axiom AssociatedConstant_value_CODECOPY : + M.IsAssociatedConstant Self "value_CODECOPY" value_CODECOPY. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_GASPRICE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 58 ] + |))). + + Axiom AssociatedConstant_value_GASPRICE : + M.IsAssociatedConstant Self "value_GASPRICE" value_GASPRICE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EXTCODESIZE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 59 ] + |))). + + Axiom AssociatedConstant_value_EXTCODESIZE : + M.IsAssociatedConstant Self "value_EXTCODESIZE" value_EXTCODESIZE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EXTCODECOPY : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 60 ] + |))). + + Axiom AssociatedConstant_value_EXTCODECOPY : + M.IsAssociatedConstant Self "value_EXTCODECOPY" value_EXTCODECOPY. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_RETURNDATASIZE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 61 ] + |))). + + Axiom AssociatedConstant_value_RETURNDATASIZE : + M.IsAssociatedConstant Self "value_RETURNDATASIZE" value_RETURNDATASIZE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_RETURNDATACOPY : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 62 ] + |))). + + Axiom AssociatedConstant_value_RETURNDATACOPY : + M.IsAssociatedConstant Self "value_RETURNDATACOPY" value_RETURNDATACOPY. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EXTCODEHASH : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 63 ] + |))). + + Axiom AssociatedConstant_value_EXTCODEHASH : + M.IsAssociatedConstant Self "value_EXTCODEHASH" value_EXTCODEHASH. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_BLOCKHASH : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 64 ] + |))). + + Axiom AssociatedConstant_value_BLOCKHASH : + M.IsAssociatedConstant Self "value_BLOCKHASH" value_BLOCKHASH. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_COINBASE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 65 ] + |))). + + Axiom AssociatedConstant_value_COINBASE : + M.IsAssociatedConstant Self "value_COINBASE" value_COINBASE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_TIMESTAMP : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 66 ] + |))). + + Axiom AssociatedConstant_value_TIMESTAMP : + M.IsAssociatedConstant Self "value_TIMESTAMP" value_TIMESTAMP. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_NUMBER : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 67 ] + |))). + + Axiom AssociatedConstant_value_NUMBER : M.IsAssociatedConstant Self "value_NUMBER" value_NUMBER. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DIFFICULTY : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 68 ] + |))). + + Axiom AssociatedConstant_value_DIFFICULTY : + M.IsAssociatedConstant Self "value_DIFFICULTY" value_DIFFICULTY. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_GASLIMIT : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 69 ] + |))). + + Axiom AssociatedConstant_value_GASLIMIT : + M.IsAssociatedConstant Self "value_GASLIMIT" value_GASLIMIT. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CHAINID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 70 ] + |))). + + Axiom AssociatedConstant_value_CHAINID : + M.IsAssociatedConstant Self "value_CHAINID" value_CHAINID. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SELFBALANCE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 71 ] + |))). + + Axiom AssociatedConstant_value_SELFBALANCE : + M.IsAssociatedConstant Self "value_SELFBALANCE" value_SELFBALANCE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_BASEFEE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 72 ] + |))). + + Axiom AssociatedConstant_value_BASEFEE : + M.IsAssociatedConstant Self "value_BASEFEE" value_BASEFEE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_BLOBHASH : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 73 ] + |))). + + Axiom AssociatedConstant_value_BLOBHASH : + M.IsAssociatedConstant Self "value_BLOBHASH" value_BLOBHASH. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_BLOBBASEFEE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 74 ] + |))). + + Axiom AssociatedConstant_value_BLOBBASEFEE : + M.IsAssociatedConstant Self "value_BLOBBASEFEE" value_BLOBBASEFEE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_POP : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 80 ] + |))). + + Axiom AssociatedConstant_value_POP : M.IsAssociatedConstant Self "value_POP" value_POP. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_MLOAD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 81 ] + |))). + + Axiom AssociatedConstant_value_MLOAD : M.IsAssociatedConstant Self "value_MLOAD" value_MLOAD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_MSTORE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 82 ] + |))). + + Axiom AssociatedConstant_value_MSTORE : M.IsAssociatedConstant Self "value_MSTORE" value_MSTORE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_MSTORE8 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 83 ] + |))). + + Axiom AssociatedConstant_value_MSTORE8 : + M.IsAssociatedConstant Self "value_MSTORE8" value_MSTORE8. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SLOAD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 84 ] + |))). + + Axiom AssociatedConstant_value_SLOAD : M.IsAssociatedConstant Self "value_SLOAD" value_SLOAD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SSTORE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 85 ] + |))). + + Axiom AssociatedConstant_value_SSTORE : M.IsAssociatedConstant Self "value_SSTORE" value_SSTORE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_JUMP : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 86 ] + |))). + + Axiom AssociatedConstant_value_JUMP : M.IsAssociatedConstant Self "value_JUMP" value_JUMP. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_JUMPI : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 87 ] + |))). + + Axiom AssociatedConstant_value_JUMPI : M.IsAssociatedConstant Self "value_JUMPI" value_JUMPI. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PC : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 88 ] + |))). + + Axiom AssociatedConstant_value_PC : M.IsAssociatedConstant Self "value_PC" value_PC. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_MSIZE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 89 ] + |))). + + Axiom AssociatedConstant_value_MSIZE : M.IsAssociatedConstant Self "value_MSIZE" value_MSIZE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_GAS : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 90 ] + |))). + + Axiom AssociatedConstant_value_GAS : M.IsAssociatedConstant Self "value_GAS" value_GAS. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_JUMPDEST : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 91 ] + |))). + + Axiom AssociatedConstant_value_JUMPDEST : + M.IsAssociatedConstant Self "value_JUMPDEST" value_JUMPDEST. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_TLOAD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 92 ] + |))). + + Axiom AssociatedConstant_value_TLOAD : M.IsAssociatedConstant Self "value_TLOAD" value_TLOAD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_TSTORE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 93 ] + |))). + + Axiom AssociatedConstant_value_TSTORE : M.IsAssociatedConstant Self "value_TSTORE" value_TSTORE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_MCOPY : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 94 ] + |))). + + Axiom AssociatedConstant_value_MCOPY : M.IsAssociatedConstant Self "value_MCOPY" value_MCOPY. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH0 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 95 ] + |))). + + Axiom AssociatedConstant_value_PUSH0 : M.IsAssociatedConstant Self "value_PUSH0" value_PUSH0. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH1 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 96 ] + |))). + + Axiom AssociatedConstant_value_PUSH1 : M.IsAssociatedConstant Self "value_PUSH1" value_PUSH1. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH2 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 97 ] + |))). + + Axiom AssociatedConstant_value_PUSH2 : M.IsAssociatedConstant Self "value_PUSH2" value_PUSH2. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH3 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 98 ] + |))). + + Axiom AssociatedConstant_value_PUSH3 : M.IsAssociatedConstant Self "value_PUSH3" value_PUSH3. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH4 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 99 ] + |))). + + Axiom AssociatedConstant_value_PUSH4 : M.IsAssociatedConstant Self "value_PUSH4" value_PUSH4. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH5 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 100 ] + |))). + + Axiom AssociatedConstant_value_PUSH5 : M.IsAssociatedConstant Self "value_PUSH5" value_PUSH5. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH6 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 101 ] + |))). + + Axiom AssociatedConstant_value_PUSH6 : M.IsAssociatedConstant Self "value_PUSH6" value_PUSH6. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH7 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 102 ] + |))). + + Axiom AssociatedConstant_value_PUSH7 : M.IsAssociatedConstant Self "value_PUSH7" value_PUSH7. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH8 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 103 ] + |))). + + Axiom AssociatedConstant_value_PUSH8 : M.IsAssociatedConstant Self "value_PUSH8" value_PUSH8. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH9 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 104 ] + |))). + + Axiom AssociatedConstant_value_PUSH9 : M.IsAssociatedConstant Self "value_PUSH9" value_PUSH9. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH10 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 105 ] + |))). + + Axiom AssociatedConstant_value_PUSH10 : M.IsAssociatedConstant Self "value_PUSH10" value_PUSH10. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH11 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 106 ] + |))). + + Axiom AssociatedConstant_value_PUSH11 : M.IsAssociatedConstant Self "value_PUSH11" value_PUSH11. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH12 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 107 ] + |))). + + Axiom AssociatedConstant_value_PUSH12 : M.IsAssociatedConstant Self "value_PUSH12" value_PUSH12. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH13 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 108 ] + |))). + + Axiom AssociatedConstant_value_PUSH13 : M.IsAssociatedConstant Self "value_PUSH13" value_PUSH13. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH14 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 109 ] + |))). + + Axiom AssociatedConstant_value_PUSH14 : M.IsAssociatedConstant Self "value_PUSH14" value_PUSH14. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH15 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 110 ] + |))). + + Axiom AssociatedConstant_value_PUSH15 : M.IsAssociatedConstant Self "value_PUSH15" value_PUSH15. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH16 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 111 ] + |))). + + Axiom AssociatedConstant_value_PUSH16 : M.IsAssociatedConstant Self "value_PUSH16" value_PUSH16. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH17 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 112 ] + |))). + + Axiom AssociatedConstant_value_PUSH17 : M.IsAssociatedConstant Self "value_PUSH17" value_PUSH17. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH18 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 113 ] + |))). + + Axiom AssociatedConstant_value_PUSH18 : M.IsAssociatedConstant Self "value_PUSH18" value_PUSH18. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH19 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 114 ] + |))). + + Axiom AssociatedConstant_value_PUSH19 : M.IsAssociatedConstant Self "value_PUSH19" value_PUSH19. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH20 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 115 ] + |))). + + Axiom AssociatedConstant_value_PUSH20 : M.IsAssociatedConstant Self "value_PUSH20" value_PUSH20. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH21 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 116 ] + |))). + + Axiom AssociatedConstant_value_PUSH21 : M.IsAssociatedConstant Self "value_PUSH21" value_PUSH21. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH22 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 117 ] + |))). + + Axiom AssociatedConstant_value_PUSH22 : M.IsAssociatedConstant Self "value_PUSH22" value_PUSH22. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH23 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 118 ] + |))). + + Axiom AssociatedConstant_value_PUSH23 : M.IsAssociatedConstant Self "value_PUSH23" value_PUSH23. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH24 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 119 ] + |))). + + Axiom AssociatedConstant_value_PUSH24 : M.IsAssociatedConstant Self "value_PUSH24" value_PUSH24. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH25 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 120 ] + |))). + + Axiom AssociatedConstant_value_PUSH25 : M.IsAssociatedConstant Self "value_PUSH25" value_PUSH25. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH26 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 121 ] + |))). + + Axiom AssociatedConstant_value_PUSH26 : M.IsAssociatedConstant Self "value_PUSH26" value_PUSH26. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH27 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 122 ] + |))). + + Axiom AssociatedConstant_value_PUSH27 : M.IsAssociatedConstant Self "value_PUSH27" value_PUSH27. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH28 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 123 ] + |))). + + Axiom AssociatedConstant_value_PUSH28 : M.IsAssociatedConstant Self "value_PUSH28" value_PUSH28. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH29 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 124 ] + |))). + + Axiom AssociatedConstant_value_PUSH29 : M.IsAssociatedConstant Self "value_PUSH29" value_PUSH29. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH30 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 125 ] + |))). + + Axiom AssociatedConstant_value_PUSH30 : M.IsAssociatedConstant Self "value_PUSH30" value_PUSH30. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH31 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 126 ] + |))). + + Axiom AssociatedConstant_value_PUSH31 : M.IsAssociatedConstant Self "value_PUSH31" value_PUSH31. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_PUSH32 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 127 ] + |))). + + Axiom AssociatedConstant_value_PUSH32 : M.IsAssociatedConstant Self "value_PUSH32" value_PUSH32. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP1 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 128 ] + |))). + + Axiom AssociatedConstant_value_DUP1 : M.IsAssociatedConstant Self "value_DUP1" value_DUP1. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP2 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 129 ] + |))). + + Axiom AssociatedConstant_value_DUP2 : M.IsAssociatedConstant Self "value_DUP2" value_DUP2. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP3 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 130 ] + |))). + + Axiom AssociatedConstant_value_DUP3 : M.IsAssociatedConstant Self "value_DUP3" value_DUP3. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP4 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 131 ] + |))). + + Axiom AssociatedConstant_value_DUP4 : M.IsAssociatedConstant Self "value_DUP4" value_DUP4. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP5 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 132 ] + |))). + + Axiom AssociatedConstant_value_DUP5 : M.IsAssociatedConstant Self "value_DUP5" value_DUP5. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP6 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 133 ] + |))). + + Axiom AssociatedConstant_value_DUP6 : M.IsAssociatedConstant Self "value_DUP6" value_DUP6. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP7 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 134 ] + |))). + + Axiom AssociatedConstant_value_DUP7 : M.IsAssociatedConstant Self "value_DUP7" value_DUP7. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP8 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 135 ] + |))). + + Axiom AssociatedConstant_value_DUP8 : M.IsAssociatedConstant Self "value_DUP8" value_DUP8. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP9 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 136 ] + |))). + + Axiom AssociatedConstant_value_DUP9 : M.IsAssociatedConstant Self "value_DUP9" value_DUP9. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP10 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 137 ] + |))). + + Axiom AssociatedConstant_value_DUP10 : M.IsAssociatedConstant Self "value_DUP10" value_DUP10. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP11 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 138 ] + |))). + + Axiom AssociatedConstant_value_DUP11 : M.IsAssociatedConstant Self "value_DUP11" value_DUP11. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP12 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 139 ] + |))). + + Axiom AssociatedConstant_value_DUP12 : M.IsAssociatedConstant Self "value_DUP12" value_DUP12. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP13 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 140 ] + |))). + + Axiom AssociatedConstant_value_DUP13 : M.IsAssociatedConstant Self "value_DUP13" value_DUP13. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP14 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 141 ] + |))). + + Axiom AssociatedConstant_value_DUP14 : M.IsAssociatedConstant Self "value_DUP14" value_DUP14. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP15 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 142 ] + |))). + + Axiom AssociatedConstant_value_DUP15 : M.IsAssociatedConstant Self "value_DUP15" value_DUP15. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUP16 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 143 ] + |))). + + Axiom AssociatedConstant_value_DUP16 : M.IsAssociatedConstant Self "value_DUP16" value_DUP16. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP1 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 144 ] + |))). + + Axiom AssociatedConstant_value_SWAP1 : M.IsAssociatedConstant Self "value_SWAP1" value_SWAP1. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP2 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 145 ] + |))). + + Axiom AssociatedConstant_value_SWAP2 : M.IsAssociatedConstant Self "value_SWAP2" value_SWAP2. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP3 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 146 ] + |))). + + Axiom AssociatedConstant_value_SWAP3 : M.IsAssociatedConstant Self "value_SWAP3" value_SWAP3. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP4 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 147 ] + |))). + + Axiom AssociatedConstant_value_SWAP4 : M.IsAssociatedConstant Self "value_SWAP4" value_SWAP4. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP5 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 148 ] + |))). + + Axiom AssociatedConstant_value_SWAP5 : M.IsAssociatedConstant Self "value_SWAP5" value_SWAP5. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP6 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 149 ] + |))). + + Axiom AssociatedConstant_value_SWAP6 : M.IsAssociatedConstant Self "value_SWAP6" value_SWAP6. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP7 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 150 ] + |))). + + Axiom AssociatedConstant_value_SWAP7 : M.IsAssociatedConstant Self "value_SWAP7" value_SWAP7. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP8 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 151 ] + |))). + + Axiom AssociatedConstant_value_SWAP8 : M.IsAssociatedConstant Self "value_SWAP8" value_SWAP8. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP9 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 152 ] + |))). + + Axiom AssociatedConstant_value_SWAP9 : M.IsAssociatedConstant Self "value_SWAP9" value_SWAP9. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP10 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 153 ] + |))). + + Axiom AssociatedConstant_value_SWAP10 : M.IsAssociatedConstant Self "value_SWAP10" value_SWAP10. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP11 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 154 ] + |))). + + Axiom AssociatedConstant_value_SWAP11 : M.IsAssociatedConstant Self "value_SWAP11" value_SWAP11. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP12 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 155 ] + |))). + + Axiom AssociatedConstant_value_SWAP12 : M.IsAssociatedConstant Self "value_SWAP12" value_SWAP12. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP13 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 156 ] + |))). + + Axiom AssociatedConstant_value_SWAP13 : M.IsAssociatedConstant Self "value_SWAP13" value_SWAP13. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP14 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 157 ] + |))). + + Axiom AssociatedConstant_value_SWAP14 : M.IsAssociatedConstant Self "value_SWAP14" value_SWAP14. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP15 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 158 ] + |))). + + Axiom AssociatedConstant_value_SWAP15 : M.IsAssociatedConstant Self "value_SWAP15" value_SWAP15. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAP16 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 159 ] + |))). + + Axiom AssociatedConstant_value_SWAP16 : M.IsAssociatedConstant Self "value_SWAP16" value_SWAP16. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_LOG0 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 160 ] + |))). + + Axiom AssociatedConstant_value_LOG0 : M.IsAssociatedConstant Self "value_LOG0" value_LOG0. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_LOG1 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 161 ] + |))). + + Axiom AssociatedConstant_value_LOG1 : M.IsAssociatedConstant Self "value_LOG1" value_LOG1. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_LOG2 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 162 ] + |))). + + Axiom AssociatedConstant_value_LOG2 : M.IsAssociatedConstant Self "value_LOG2" value_LOG2. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_LOG3 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 163 ] + |))). + + Axiom AssociatedConstant_value_LOG3 : M.IsAssociatedConstant Self "value_LOG3" value_LOG3. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_LOG4 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 164 ] + |))). + + Axiom AssociatedConstant_value_LOG4 : M.IsAssociatedConstant Self "value_LOG4" value_LOG4. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DATALOAD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 208 ] + |))). + + Axiom AssociatedConstant_value_DATALOAD : + M.IsAssociatedConstant Self "value_DATALOAD" value_DATALOAD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DATALOADN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 209 ] + |))). + + Axiom AssociatedConstant_value_DATALOADN : + M.IsAssociatedConstant Self "value_DATALOADN" value_DATALOADN. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DATASIZE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 210 ] + |))). + + Axiom AssociatedConstant_value_DATASIZE : + M.IsAssociatedConstant Self "value_DATASIZE" value_DATASIZE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DATACOPY : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 211 ] + |))). + + Axiom AssociatedConstant_value_DATACOPY : + M.IsAssociatedConstant Self "value_DATACOPY" value_DATACOPY. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_RJUMP : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 224 ] + |))). + + Axiom AssociatedConstant_value_RJUMP : M.IsAssociatedConstant Self "value_RJUMP" value_RJUMP. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_RJUMPI : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 225 ] + |))). + + Axiom AssociatedConstant_value_RJUMPI : M.IsAssociatedConstant Self "value_RJUMPI" value_RJUMPI. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_RJUMPV : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 226 ] + |))). + + Axiom AssociatedConstant_value_RJUMPV : M.IsAssociatedConstant Self "value_RJUMPV" value_RJUMPV. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CALLF : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 227 ] + |))). + + Axiom AssociatedConstant_value_CALLF : M.IsAssociatedConstant Self "value_CALLF" value_CALLF. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_RETF : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 228 ] + |))). + + Axiom AssociatedConstant_value_RETF : M.IsAssociatedConstant Self "value_RETF" value_RETF. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_JUMPF : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 229 ] + |))). + + Axiom AssociatedConstant_value_JUMPF : M.IsAssociatedConstant Self "value_JUMPF" value_JUMPF. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DUPN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 230 ] + |))). + + Axiom AssociatedConstant_value_DUPN : M.IsAssociatedConstant Self "value_DUPN" value_DUPN. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SWAPN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 231 ] + |))). + + Axiom AssociatedConstant_value_SWAPN : M.IsAssociatedConstant Self "value_SWAPN" value_SWAPN. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EXCHANGE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 232 ] + |))). + + Axiom AssociatedConstant_value_EXCHANGE : + M.IsAssociatedConstant Self "value_EXCHANGE" value_EXCHANGE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EOFCREATE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 236 ] + |))). + + Axiom AssociatedConstant_value_EOFCREATE : + M.IsAssociatedConstant Self "value_EOFCREATE" value_EOFCREATE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_TXCREATE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 237 ] + |))). + + Axiom AssociatedConstant_value_TXCREATE : + M.IsAssociatedConstant Self "value_TXCREATE" value_TXCREATE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_RETURNCONTRACT : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 238 ] + |))). + + Axiom AssociatedConstant_value_RETURNCONTRACT : + M.IsAssociatedConstant Self "value_RETURNCONTRACT" value_RETURNCONTRACT. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CREATE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 240 ] + |))). + + Axiom AssociatedConstant_value_CREATE : M.IsAssociatedConstant Self "value_CREATE" value_CREATE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CALL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 241 ] + |))). + + Axiom AssociatedConstant_value_CALL : M.IsAssociatedConstant Self "value_CALL" value_CALL. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CALLCODE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 242 ] + |))). + + Axiom AssociatedConstant_value_CALLCODE : + M.IsAssociatedConstant Self "value_CALLCODE" value_CALLCODE. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_RETURN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 243 ] + |))). + + Axiom AssociatedConstant_value_RETURN : M.IsAssociatedConstant Self "value_RETURN" value_RETURN. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_DELEGATECALL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 244 ] + |))). + + Axiom AssociatedConstant_value_DELEGATECALL : + M.IsAssociatedConstant Self "value_DELEGATECALL" value_DELEGATECALL. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_CREATE2 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 245 ] + |))). + + Axiom AssociatedConstant_value_CREATE2 : + M.IsAssociatedConstant Self "value_CREATE2" value_CREATE2. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_RETURNDATALOAD : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 247 ] + |))). + + Axiom AssociatedConstant_value_RETURNDATALOAD : + M.IsAssociatedConstant Self "value_RETURNDATALOAD" value_RETURNDATALOAD. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EXTCALL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 248 ] + |))). + + Axiom AssociatedConstant_value_EXTCALL : + M.IsAssociatedConstant Self "value_EXTCALL" value_EXTCALL. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EXFCALL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 249 ] + |))). + + Axiom AssociatedConstant_value_EXFCALL : + M.IsAssociatedConstant Self "value_EXFCALL" value_EXFCALL. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_STATICCALL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 250 ] + |))). + + Axiom AssociatedConstant_value_STATICCALL : + M.IsAssociatedConstant Self "value_STATICCALL" value_STATICCALL. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_EXTSCALL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 251 ] + |))). + + Axiom AssociatedConstant_value_EXTSCALL : + M.IsAssociatedConstant Self "value_EXTSCALL" value_EXTSCALL. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_REVERT : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 253 ] + |))). + + Axiom AssociatedConstant_value_REVERT : M.IsAssociatedConstant Self "value_REVERT" value_REVERT. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_INVALID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 254 ] + |))). + + Axiom AssociatedConstant_value_INVALID : + M.IsAssociatedConstant Self "value_INVALID" value_INVALID. + + (* pub const $name: Self = Self($val); *) + (* Ty.path "revm_interpreter::opcode::OpCode" *) + Definition value_SELFDESTRUCT : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_interpreter::opcode::OpCode" [ Value.Integer 255 ] + |))). + + Axiom AssociatedConstant_value_SELFDESTRUCT : + M.IsAssociatedConstant Self "value_SELFDESTRUCT" value_SELFDESTRUCT. + End Impl_revm_interpreter_opcode_OpCode. + + (* StructRecord + { + name := "OpCodeInfo"; + ty_params := []; + fields := + [ + ("name_ptr", Ty.apply (Ty.path "core::ptr::non_null::NonNull") [ Ty.path "u8" ]); + ("name_len", Ty.path "u8"); + ("inputs", Ty.path "u8"); + ("outputs", Ty.path "u8"); + ("immediate_size", Ty.path "u8"); + ("not_eof", Ty.path "bool"); + ("terminating", Ty.path "bool") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_core_marker_Copy_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_core_marker_StructuralPartialEq_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_core_cmp_PartialEq_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "core::ptr::non_null::NonNull") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ptr::non_null::NonNull") [ Ty.path "u8" ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_ptr" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "name_ptr" + |) + ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_len" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "name_len" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "not_eof" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "not_eof" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "terminating" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "terminating" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_core_marker_StructuralEq_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_core_cmp_Eq_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_core_cmp_PartialOrd_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.apply (Ty.path "core::ptr::non_null::NonNull") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ptr::non_null::NonNull") [ Ty.path "u8" ] ], + "partial_cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_ptr" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "name_ptr" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let _ := M.is_struct_tuple (| ฮณ0_0, "core::cmp::Ordering::Equal" |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "u8", + [ Ty.path "u8" ], + "partial_cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_len" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "name_len" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let _ := M.is_struct_tuple (| ฮณ0_0, "core::cmp::Ordering::Equal" |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "u8", + [ Ty.path "u8" ], + "partial_cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let _ := + M.is_struct_tuple (| ฮณ0_0, "core::cmp::Ordering::Equal" |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "u8", + [ Ty.path "u8" ], + "partial_cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let _ := + M.is_struct_tuple (| + ฮณ0_0, + "core::cmp::Ordering::Equal" + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "u8", + [ Ty.path "u8" ], + "partial_cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let _ := + M.is_struct_tuple (| + ฮณ0_0, + "core::cmp::Ordering::Equal" + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "bool", + [ Ty.path "bool" ], + "partial_cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "not_eof" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "not_eof" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let _ := + M.is_struct_tuple (| + ฮณ0_0, + "core::cmp::Ordering::Equal" + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "bool", + [ Ty.path "bool" ], + "partial_cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "terminating" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "terminating" + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_core_cmp_Ord_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.apply (Ty.path "core::ptr::non_null::NonNull") [ Ty.path "u8" ], + [], + "cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_ptr" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "name_ptr" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::cmp::Ordering::Equal" |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "u8", [], "cmp", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_len" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "name_len" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::cmp::Ordering::Equal" |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "u8", + [], + "cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::cmp::Ordering::Equal" |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "u8", + [], + "cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::cmp::Ordering::Equal" + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "u8", + [], + "cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::cmp::Ordering::Equal" + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "bool", + [], + "cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "not_eof" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "not_eof" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::cmp::Ordering::Equal" + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "bool", + [], + "cmp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "terminating" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_interpreter::opcode::OpCodeInfo", + "terminating" + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let cmp := M.copy (| ฮณ |) in + cmp)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_core_hash_Hash_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply (Ty.path "core::ptr::non_null::NonNull") [ Ty.path "u8" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_ptr" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u8", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_len" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u8", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u8", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u8", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "bool", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "not_eof" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "bool", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "terminating" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_core_fmt_Debug_for_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OpCodeInfo") + .field("name", &self.name()) + .field("inputs", &self.inputs()) + .field("outputs", &self.outputs()) + .field("not_eof", &self.is_disabled_in_eof()) + .field("terminating", &self.is_terminating()) + .field("immediate_size", &self.immediate_size()) + .finish() + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "finish", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct", + [] + |), + [ M.read (| f |); M.read (| Value.String "OpCodeInfo" |) ] + |) + |); + M.read (| Value.String "name" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "name", + [] + |), + [ M.read (| self |) ] + |) + |)) + ] + |); + M.read (| Value.String "inputs" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "inputs", + [] + |), + [ M.read (| self |) ] + |) + |)) + ] + |); + M.read (| Value.String "outputs" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "outputs", + [] + |), + [ M.read (| self |) ] + |) + |)) + ] + |); + M.read (| Value.String "not_eof" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "is_disabled_in_eof", + [] + |), + [ M.read (| self |) ] + |) + |)) + ] + |); + M.read (| Value.String "terminating" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "is_terminating", + [] + |), + [ M.read (| self |) ] + |) + |)) + ] + |); + M.read (| Value.String "immediate_size" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ M.read (| self |) ] + |) + |)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_interpreter_opcode_OpCodeInfo. + + Module Impl_revm_interpreter_opcode_OpCodeInfo. + Definition Self : Ty.t := Ty.path "revm_interpreter::opcode::OpCodeInfo". + + (* + pub const fn new(name: &'static str) -> Self { + assert!(name.len() < 256, "opcode name is too long"); + Self { + name_ptr: unsafe { NonNull::new_unchecked(name.as_ptr().cast_mut()) }, + name_len: name.len() as u8, + inputs: 0, + outputs: 0, + not_eof: false, + terminating: false, + immediate_size: 0, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ name ] => + ltac:(M.monadic + (let name := M.alloc (| name |) in + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| Ty.path "str", "len", [] |), + [ M.read (| name |) ] + |)) + (Value.Integer 256)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "opcode name is too long" |) ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructRecord + "revm_interpreter::opcode::OpCodeInfo" + [ + ("name_ptr", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::ptr::non_null::NonNull") [ Ty.path "u8" ], + "new_unchecked", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "cast_mut", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "str", "as_ptr", [] |), + [ M.read (| name |) ] + |) + ] + |) + ] + |)); + ("name_len", + M.rust_cast + (M.call_closure (| + M.get_associated_function (| Ty.path "str", "len", [] |), + [ M.read (| name |) ] + |))); + ("inputs", Value.Integer 0); + ("outputs", Value.Integer 0); + ("not_eof", Value.Bool false); + ("terminating", Value.Bool false); + ("immediate_size", Value.Integer 0) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub const fn name(&self) -> &'static str { + // SAFETY: `self.name_*` can only be initialized with a valid `&'static str`. + unsafe { + // TODO: Use `str::from_raw_parts` when it's stable. + let slice = core::slice::from_raw_parts(self.name_ptr.as_ptr(), self.name_len as usize); + core::str::from_utf8_unchecked(slice) + } + } + *) + Definition name (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ slice := + M.alloc (| + M.call_closure (| + M.get_function (| "core::slice::raw::from_raw_parts", [ Ty.path "u8" ] |), + [ + (* MutToConstPointer *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::ptr::non_null::NonNull") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_ptr" + |) + |) + ] + |)); + M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "name_len" + |) + |)) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_function (| "core::str::converts::from_utf8_unchecked", [] |), + [ M.read (| slice |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_name : M.IsAssociatedFunction Self "name" name. + + (* + pub const fn io_diff(&self) -> i16 { + self.outputs as i16 - self.inputs as i16 + } + *) + Definition io_diff (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.sub + Integer.I16 + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |) + |))) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |) + |))))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_io_diff : M.IsAssociatedFunction Self "io_diff" io_diff. + + (* + pub const fn inputs(&self) -> u8 { + self.inputs + } + *) + Definition inputs (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_inputs : M.IsAssociatedFunction Self "inputs" inputs. + + (* + pub const fn outputs(&self) -> u8 { + self.outputs + } + *) + Definition outputs (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_outputs : M.IsAssociatedFunction Self "outputs" outputs. + + (* + pub const fn is_disabled_in_eof(&self) -> bool { + self.not_eof + } + *) + Definition is_disabled_in_eof (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "not_eof" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_disabled_in_eof : + M.IsAssociatedFunction Self "is_disabled_in_eof" is_disabled_in_eof. + + (* + pub const fn is_terminating(&self) -> bool { + self.terminating + } + *) + Definition is_terminating (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "terminating" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_terminating : + M.IsAssociatedFunction Self "is_terminating" is_terminating. + + (* + pub const fn immediate_size(&self) -> u8 { + self.immediate_size + } + *) + Definition immediate_size (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_immediate_size : + M.IsAssociatedFunction Self "immediate_size" immediate_size. + End Impl_revm_interpreter_opcode_OpCodeInfo. + + (* + pub const fn not_eof(mut op: OpCodeInfo) -> OpCodeInfo { + op.not_eof = true; + op + } + *) + Definition not_eof (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ op ] => + ltac:(M.monadic + (let op := M.alloc (| op |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + op, + "revm_interpreter::opcode::OpCodeInfo", + "not_eof" + |), + Value.Bool true + |) in + op + |))) + | _, _ => M.impossible + end. + + Axiom Function_not_eof : M.IsFunction "revm_interpreter::opcode::not_eof" not_eof. + + (* + pub const fn immediate_size(mut op: OpCodeInfo, n: u8) -> OpCodeInfo { + op.immediate_size = n; + op + } + *) + Definition immediate_size (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ op; n ] => + ltac:(M.monadic + (let op := M.alloc (| op |) in + let n := M.alloc (| n |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + op, + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size" + |), + M.read (| n |) + |) in + op + |))) + | _, _ => M.impossible + end. + + Axiom Function_immediate_size : + M.IsFunction "revm_interpreter::opcode::immediate_size" immediate_size. + + (* + pub const fn terminating(mut op: OpCodeInfo) -> OpCodeInfo { + op.terminating = true; + op + } + *) + Definition terminating (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ op ] => + ltac:(M.monadic + (let op := M.alloc (| op |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + op, + "revm_interpreter::opcode::OpCodeInfo", + "terminating" + |), + Value.Bool true + |) in + op + |))) + | _, _ => M.impossible + end. + + Axiom Function_terminating : M.IsFunction "revm_interpreter::opcode::terminating" terminating. + + (* + pub const fn stack_io(mut op: OpCodeInfo, inputs: u8, outputs: u8) -> OpCodeInfo { + op.inputs = inputs; + op.outputs = outputs; + op + } + *) + Definition stack_io (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ op; inputs; outputs ] => + ltac:(M.monadic + (let op := M.alloc (| op |) in + let inputs := M.alloc (| inputs |) in + let outputs := M.alloc (| outputs |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + op, + "revm_interpreter::opcode::OpCodeInfo", + "inputs" + |), + M.read (| inputs |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + op, + "revm_interpreter::opcode::OpCodeInfo", + "outputs" + |), + M.read (| outputs |) + |) in + op + |))) + | _, _ => M.impossible + end. + + Axiom Function_stack_io : M.IsFunction "revm_interpreter::opcode::stack_io" stack_io. + + Definition value_NOP : Value.t := + M.run ltac:(M.monadic (M.get_constant (| "revm_interpreter::opcode::JUMPDEST" |))). + + Definition value_STOP : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 0 |))). + + Definition value_ADD : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 1 |))). + + Definition value_MUL : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 2 |))). + + Definition value_SUB : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 3 |))). + + Definition value_DIV : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 4 |))). + + Definition value_SDIV : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 5 |))). + + Definition value_MOD : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 6 |))). + + Definition value_SMOD : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 7 |))). + + Definition value_ADDMOD : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 8 |))). + + Definition value_MULMOD : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 9 |))). + + Definition value_EXP : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 10 |))). + + Definition value_SIGNEXTEND : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 11 |))). + + Definition value_LT : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 16 |))). + + Definition value_GT : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 17 |))). + + Definition value_SLT : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 18 |))). + + Definition value_SGT : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 19 |))). + + Definition value_EQ : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 20 |))). + + Definition value_ISZERO : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 21 |))). + + Definition value_AND : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 22 |))). + + Definition value_OR : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 23 |))). + + Definition value_XOR : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 24 |))). + + Definition value_NOT : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 25 |))). + + Definition value_BYTE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 26 |))). + + Definition value_SHL : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 27 |))). + + Definition value_SHR : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 28 |))). + + Definition value_SAR : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 29 |))). + + Definition value_KECCAK256 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 32 |))). + + Definition value_ADDRESS : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 48 |))). + + Definition value_BALANCE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 49 |))). + + Definition value_ORIGIN : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 50 |))). + + Definition value_CALLER : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 51 |))). + + Definition value_CALLVALUE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 52 |))). + + Definition value_CALLDATALOAD : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 53 |))). + + Definition value_CALLDATASIZE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 54 |))). + + Definition value_CALLDATACOPY : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 55 |))). + + Definition value_CODESIZE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 56 |))). + + Definition value_CODECOPY : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 57 |))). + + Definition value_GASPRICE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 58 |))). + + Definition value_EXTCODESIZE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 59 |))). + + Definition value_EXTCODECOPY : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 60 |))). + + Definition value_RETURNDATASIZE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 61 |))). + + Definition value_RETURNDATACOPY : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 62 |))). + + Definition value_EXTCODEHASH : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 63 |))). + + Definition value_BLOCKHASH : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 64 |))). + + Definition value_COINBASE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 65 |))). + + Definition value_TIMESTAMP : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 66 |))). + + Definition value_NUMBER : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 67 |))). + + Definition value_DIFFICULTY : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 68 |))). + + Definition value_GASLIMIT : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 69 |))). + + Definition value_CHAINID : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 70 |))). + + Definition value_SELFBALANCE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 71 |))). + + Definition value_BASEFEE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 72 |))). + + Definition value_BLOBHASH : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 73 |))). + + Definition value_BLOBBASEFEE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 74 |))). + + Definition value_POP : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 80 |))). + + Definition value_MLOAD : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 81 |))). + + Definition value_MSTORE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 82 |))). + + Definition value_MSTORE8 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 83 |))). + + Definition value_SLOAD : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 84 |))). + + Definition value_SSTORE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 85 |))). + + Definition value_JUMP : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 86 |))). + + Definition value_JUMPI : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 87 |))). + + Definition value_PC : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 88 |))). + + Definition value_MSIZE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 89 |))). + + Definition value_GAS : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 90 |))). + + Definition value_JUMPDEST : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 91 |))). + + Definition value_TLOAD : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 92 |))). + + Definition value_TSTORE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 93 |))). + + Definition value_MCOPY : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 94 |))). + + Definition value_PUSH0 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 95 |))). + + Definition value_PUSH1 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 96 |))). + + Definition value_PUSH2 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 97 |))). + + Definition value_PUSH3 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 98 |))). + + Definition value_PUSH4 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 99 |))). + + Definition value_PUSH5 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 100 |))). + + Definition value_PUSH6 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 101 |))). + + Definition value_PUSH7 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 102 |))). + + Definition value_PUSH8 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 103 |))). + + Definition value_PUSH9 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 104 |))). + + Definition value_PUSH10 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 105 |))). + + Definition value_PUSH11 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 106 |))). + + Definition value_PUSH12 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 107 |))). + + Definition value_PUSH13 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 108 |))). + + Definition value_PUSH14 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 109 |))). + + Definition value_PUSH15 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 110 |))). + + Definition value_PUSH16 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 111 |))). + + Definition value_PUSH17 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 112 |))). + + Definition value_PUSH18 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 113 |))). + + Definition value_PUSH19 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 114 |))). + + Definition value_PUSH20 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 115 |))). + + Definition value_PUSH21 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 116 |))). + + Definition value_PUSH22 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 117 |))). + + Definition value_PUSH23 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 118 |))). + + Definition value_PUSH24 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 119 |))). + + Definition value_PUSH25 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 120 |))). + + Definition value_PUSH26 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 121 |))). + + Definition value_PUSH27 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 122 |))). + + Definition value_PUSH28 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 123 |))). + + Definition value_PUSH29 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 124 |))). + + Definition value_PUSH30 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 125 |))). + + Definition value_PUSH31 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 126 |))). + + Definition value_PUSH32 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 127 |))). + + Definition value_DUP1 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 128 |))). + + Definition value_DUP2 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 129 |))). + + Definition value_DUP3 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 130 |))). + + Definition value_DUP4 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 131 |))). + + Definition value_DUP5 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 132 |))). + + Definition value_DUP6 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 133 |))). + + Definition value_DUP7 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 134 |))). + + Definition value_DUP8 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 135 |))). + + Definition value_DUP9 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 136 |))). + + Definition value_DUP10 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 137 |))). + + Definition value_DUP11 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 138 |))). + + Definition value_DUP12 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 139 |))). + + Definition value_DUP13 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 140 |))). + + Definition value_DUP14 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 141 |))). + + Definition value_DUP15 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 142 |))). + + Definition value_DUP16 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 143 |))). + + Definition value_SWAP1 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 144 |))). + + Definition value_SWAP2 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 145 |))). + + Definition value_SWAP3 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 146 |))). + + Definition value_SWAP4 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 147 |))). + + Definition value_SWAP5 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 148 |))). + + Definition value_SWAP6 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 149 |))). + + Definition value_SWAP7 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 150 |))). + + Definition value_SWAP8 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 151 |))). + + Definition value_SWAP9 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 152 |))). + + Definition value_SWAP10 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 153 |))). + + Definition value_SWAP11 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 154 |))). + + Definition value_SWAP12 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 155 |))). + + Definition value_SWAP13 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 156 |))). + + Definition value_SWAP14 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 157 |))). + + Definition value_SWAP15 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 158 |))). + + Definition value_SWAP16 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 159 |))). + + Definition value_LOG0 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 160 |))). + + Definition value_LOG1 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 161 |))). + + Definition value_LOG2 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 162 |))). + + Definition value_LOG3 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 163 |))). + + Definition value_LOG4 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 164 |))). + + Definition value_DATALOAD : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 208 |))). + + Definition value_DATALOADN : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 209 |))). + + Definition value_DATASIZE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 210 |))). + + Definition value_DATACOPY : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 211 |))). + + Definition value_RJUMP : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 224 |))). + + Definition value_RJUMPI : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 225 |))). + + Definition value_RJUMPV : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 226 |))). + + Definition value_CALLF : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 227 |))). + + Definition value_RETF : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 228 |))). + + Definition value_JUMPF : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 229 |))). + + Definition value_DUPN : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 230 |))). + + Definition value_SWAPN : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 231 |))). + + Definition value_EXCHANGE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 232 |))). + + Definition value_EOFCREATE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 236 |))). + + Definition value_TXCREATE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 237 |))). + + Definition value_RETURNCONTRACT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 238 |))). + + Definition value_CREATE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 240 |))). + + Definition value_CALL : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 241 |))). + + Definition value_CALLCODE : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 242 |))). + + Definition value_RETURN : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 243 |))). + + Definition value_DELEGATECALL : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 244 |))). + + Definition value_CREATE2 : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 245 |))). + + Definition value_RETURNDATALOAD : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 247 |))). + + Definition value_EXTCALL : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 248 |))). + + Definition value_EXFCALL : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 249 |))). + + Definition value_STATICCALL : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 250 |))). + + Definition value_EXTSCALL : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 251 |))). + + Definition value_REVERT : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 253 |))). + + Definition value_INVALID : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 254 |))). + + Definition value_SELFDESTRUCT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 255 |))). + + + Definition value_OPCODE_INFO_JUMPTABLE : Value.t := + M.run + ltac:(M.monadic + (let~ map := M.alloc (| repeat (Value.StructTuple "core::option::Option::None" []) 256 |) in + let~ prev := M.alloc (| Value.Integer 0 |) in + let~ val := M.alloc (| Value.Integer 0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "STOP" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::terminating", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 0 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "ADD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 1 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 2 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "MUL" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 2 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 3 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SUB" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 3 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 4 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DIV" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 4 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 5 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SDIV" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 5 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 6 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "MOD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 6 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 7 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SMOD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 7 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 8 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "ADDMOD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 8 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 9 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "MULMOD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 9 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 10 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EXP" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 10 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 11 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SIGNEXTEND" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 11 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 16 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "LT" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 16 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 17 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "GT" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 17 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 18 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SLT" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 18 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 19 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SGT" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 19 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 20 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EQ" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 20 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 21 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "ISZERO" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 21 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 22 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "AND" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 22 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 23 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "OR" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 23 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 24 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "XOR" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 24 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 25 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "NOT" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 25 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 26 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "BYTE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 26 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 27 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SHL" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 27 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 28 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SHR" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 28 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 29 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SAR" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 29 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 32 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "KECCAK256" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 32 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 48 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "ADDRESS" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 48 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 49 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "BALANCE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 49 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 50 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "ORIGIN" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 50 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 51 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CALLER" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 51 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 52 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CALLVALUE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 52 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 53 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CALLDATALOAD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 53 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 54 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CALLDATASIZE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 54 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 55 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CALLDATACOPY" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 55 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 56 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CODESIZE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 56 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 57 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CODECOPY" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 57 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 58 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "GASPRICE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 58 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 59 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EXTCODESIZE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 59 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 60 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EXTCODECOPY" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 4; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 60 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 61 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "RETURNDATASIZE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 61 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 62 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "RETURNDATACOPY" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 62 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 63 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EXTCODEHASH" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 63 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 64 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "BLOCKHASH" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 64 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 65 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "COINBASE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 65 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 66 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "TIMESTAMP" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 66 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 67 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "NUMBER" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 67 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 68 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DIFFICULTY" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 68 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 69 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "GASLIMIT" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 69 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 70 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CHAINID" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 70 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 71 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SELFBALANCE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 71 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 72 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "BASEFEE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 72 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 73 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "BLOBHASH" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 73 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 74 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "BLOBBASEFEE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 74 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 80 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "POP" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 80 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 81 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "MLOAD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 81 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 82 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "MSTORE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 82 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 83 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "MSTORE8" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 83 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 84 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SLOAD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 84 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 85 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SSTORE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 85 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 86 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "JUMP" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 86 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 87 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "JUMPI" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 87 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 88 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PC" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 88 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 89 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "MSIZE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 89 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 90 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "GAS" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 90 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 91 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "JUMPDEST" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 91 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 92 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "TLOAD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 92 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 93 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "TSTORE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 93 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 94 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "MCOPY" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 94 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 95 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH0" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 95 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 96 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH1" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 96 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 97 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH2" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 2 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 97 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 98 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH3" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 3 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 98 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 99 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH4" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 4 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 99 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 100 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH5" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 5 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 100 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 101 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH6" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 6 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 101 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 102 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH7" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 7 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 102 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 103 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH8" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 8 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 103 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 104 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH9" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 9 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 104 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 105 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH10" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 10 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 105 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 106 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH11" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 11 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 106 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 107 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH12" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 12 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 107 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 108 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH13" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 13 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 108 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 109 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH14" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 14 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 109 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 110 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH15" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 15 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 110 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 111 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH16" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 16 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 111 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 112 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH17" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 17 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 112 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 113 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH18" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 18 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 113 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 114 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH19" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 19 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 114 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 115 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH20" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 20 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 115 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 116 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH21" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 21 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 116 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 117 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH22" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 22 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 117 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 118 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH23" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 23 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 118 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 119 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH24" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 24 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 119 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 120 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH25" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 25 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 120 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 121 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH26" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 26 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 121 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 122 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH27" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 27 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 122 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 123 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH28" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 28 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 123 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 124 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH29" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 29 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 124 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 125 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH30" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 30 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 125 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 126 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH31" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 31 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 126 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 127 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "PUSH32" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 32 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 127 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 128 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP1" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 2 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 128 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 129 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP2" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 3 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 129 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 130 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP3" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 4 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 130 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 131 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP4" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 4; Value.Integer 5 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 131 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 132 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP5" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 5; Value.Integer 6 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 132 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 133 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP6" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 6; Value.Integer 7 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 133 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 134 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP7" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 7; Value.Integer 8 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 134 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 135 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP8" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 8; Value.Integer 9 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 135 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 136 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP9" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 9; Value.Integer 10 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 136 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 137 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP10" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 10; Value.Integer 11 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 137 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 138 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP11" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 11; Value.Integer 12 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 138 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 139 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP12" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 12; Value.Integer 13 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 139 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 140 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP13" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 13; Value.Integer 14 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 140 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 141 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP14" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 14; Value.Integer 15 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 141 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 142 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP15" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 15; Value.Integer 16 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 142 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 143 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUP16" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 16; Value.Integer 17 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 143 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 144 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP1" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 2 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 144 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 145 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP2" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 3 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 145 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 146 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP3" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 4; Value.Integer 4 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 146 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 147 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP4" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 5; Value.Integer 5 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 147 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 148 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP5" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 6; Value.Integer 6 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 148 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 149 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP6" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 7; Value.Integer 7 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 149 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 150 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP7" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 8; Value.Integer 8 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 150 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 151 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP8" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 9; Value.Integer 9 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 151 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 152 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP9" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 10; Value.Integer 10 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 152 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 153 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP10" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 11; Value.Integer 11 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 153 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 154 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP11" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 12; Value.Integer 12 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 154 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 155 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP12" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 13; Value.Integer 13 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 155 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 156 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP13" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 14; Value.Integer 14 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 156 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 157 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP14" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 15; Value.Integer 15 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 157 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 158 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP15" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 16; Value.Integer 16 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 158 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 159 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAP16" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 17; Value.Integer 17 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 159 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 160 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "LOG0" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 160 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 161 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "LOG1" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 161 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 162 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "LOG2" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 4; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 162 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 163 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "LOG3" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 5; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 163 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 164 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "LOG4" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 6; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 164 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 208 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DATALOAD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 208 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 209 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DATALOADN" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 2 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 209 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 210 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DATASIZE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 210 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 211 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DATACOPY" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 0 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 211 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 224 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "RJUMP" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 2 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::terminating", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 224 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 225 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "RJUMPI" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 2 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 225 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 226 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "RJUMPV" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 226 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 227 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CALLF" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 2 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 227 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 228 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "RETF" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::terminating", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 228 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 229 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "JUMPF" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 2 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::terminating", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 229 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 230 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DUPN" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 230 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 231 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SWAPN" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 231 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 232 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EXCHANGE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 232 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 236 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EOFCREATE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 4; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 236 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 237 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "TXCREATE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 5; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 237 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 238 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "RETURNCONTRACT" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::immediate_size", [] |), + [ M.read (| info |); Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::terminating", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 238 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 240 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CREATE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 240 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 241 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CALL" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 7; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 241 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 242 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CALLCODE" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 7; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 242 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 243 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "RETURN" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::terminating", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 243 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 244 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "DELEGATECALL" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 6; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 244 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 245 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "CREATE2" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 4; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 245 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 247 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "RETURNDATALOAD" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 247 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 248 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EXTCALL" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 4; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 248 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 249 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EXFCALL" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 249 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 250 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "STATICCALL" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 6; Value.Integer 1 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 250 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 251 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "EXTSCALL" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 3; Value.Integer 1 ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 251 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 253 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "REVERT" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 2; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::terminating", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 253 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 254 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "INVALID" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 0; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::terminating", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 254 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + let~ val := M.alloc (| Value.Integer 255 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.or (| + BinOp.Pure.eq (M.read (| val |)) (Value.Integer 0), + ltac:(M.monadic (BinOp.Pure.gt (M.read (| val |)) (M.read (| prev |)))) + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "opcodes must be sorted in ascending order" + |) + ] + |)) + ] + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := M.write (| prev, M.read (| val |) |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "new", + [] + |), + [ M.read (| Value.String "SELFDESTRUCT" |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::stack_io", [] |), + [ M.read (| info |); Value.Integer 1; Value.Integer 0 ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::not_eof", [] |), + [ M.read (| info |) ] + |) + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_interpreter::opcode::terminating", [] |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| map, M.alloc (| Value.Integer 255 |) |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |) in + M.match_operator (| prev, [ fun ฮณ => ltac:(M.monadic map) ] |))). + + Definition value_NAME_TO_OPCODE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.alloc (| + Value.StructRecord + "phf::map::Map" + [ + ("key", Value.Integer 12913932095322966823); + ("disps", + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + Value.Tuple [ Value.Integer 0; Value.Integer 27 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 3 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 155 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 0 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 153 ]; + Value.Tuple [ Value.Integer 26; Value.Integer 134 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 135 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 123 ]; + Value.Tuple [ Value.Integer 2; Value.Integer 3 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 70 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 0 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 100 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 4 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 111 ]; + Value.Tuple [ Value.Integer 2; Value.Integer 33 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 0 ]; + Value.Tuple [ Value.Integer 1; Value.Integer 154 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 8 ]; + Value.Tuple [ Value.Integer 1; Value.Integer 49 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 1 ]; + Value.Tuple [ Value.Integer 7; Value.Integer 29 ]; + Value.Tuple [ Value.Integer 39; Value.Integer 151 ]; + Value.Tuple [ Value.Integer 2; Value.Integer 77 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 55 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 17 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 75 ]; + Value.Tuple [ Value.Integer 15; Value.Integer 42 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 2 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 3 ]; + Value.Tuple [ Value.Integer 2; Value.Integer 32 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 5 ]; + Value.Tuple [ Value.Integer 1; Value.Integer 18 ]; + Value.Tuple [ Value.Integer 0; Value.Integer 2 ]; + Value.Tuple [ Value.Integer 69; Value.Integer 21 ] + ] + |))); + ("entries", + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + Value.Tuple + [ + M.read (| Value.String "RETURN" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::RETURN" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH15" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH15" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP6" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP6" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH27" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH27" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "JUMPDEST" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::JUMPDEST" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "TIMESTAMP" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::TIMESTAMP" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH7" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH7" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SELFDESTRUCT" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::SELFDESTRUCT" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "ISZERO" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::ISZERO" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SLOAD" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SLOAD" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP1" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP1" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH20" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH20" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "RETURNDATACOPY" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::RETURNDATACOPY" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "EXTSCALL" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::EXTSCALL" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "JUMPI" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::JUMPI" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DATASIZE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DATASIZE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP15" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP15" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP10" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP10" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP1" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP1" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH30" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH30" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CREATE2" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::CREATE2" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "LOG3" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::LOG3" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CALL" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::CALL" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP9" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP9" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "BLOCKHASH" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::BLOCKHASH" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "BLOBHASH" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::BLOBHASH" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "LOG1" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::LOG1" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP2" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP2" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "EQ" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::EQ" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "MCOPY" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::MCOPY" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "RJUMP" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::RJUMP" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "GAS" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::GAS" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "LOG0" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::LOG0" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "EXTCODEHASH" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::EXTCODEHASH" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH12" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH12" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CALLDATACOPY" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::CALLDATACOPY" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "RETURNDATALOAD" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::RETURNDATALOAD" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH17" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH17" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "BASEFEE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::BASEFEE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "MLOAD" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::MLOAD" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "TXCREATE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::TXCREATE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP15" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP15" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SMOD" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SMOD" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "EOFCREATE" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::EOFCREATE" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP10" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP10" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "ADDMOD" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::ADDMOD" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "RJUMPI" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::RJUMPI" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "GASPRICE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::GASPRICE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH23" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH23" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP12" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP12" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP7" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP7" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "EXTCALL" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::EXTCALL" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "LT" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::LT" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH3" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH3" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SDIV" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SDIV" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "EXTCODESIZE" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::EXTCODESIZE" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP4" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP4" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CALLDATALOAD" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::CALLDATALOAD" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH13" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH13" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "JUMP" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::JUMP" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP6" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP6" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "MOD" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::MOD" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "INVALID" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::INVALID" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH31" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH31" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH29" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH29" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP8" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP8" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CALLER" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::CALLER" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH25" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH25" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH2" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH2" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP16" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP16" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP14" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP14" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH14" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH14" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUPN" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUPN" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DATALOADN" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::DATALOADN" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "CHAINID" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::CHAINID" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH10" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH10" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH9" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH9" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP3" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP3" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "EXCHANGE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::EXCHANGE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP2" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP2" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "EXTCODECOPY" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::EXTCODECOPY" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "MULMOD" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::MULMOD" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH11" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH11" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "ORIGIN" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::ORIGIN" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "POP" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::POP" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP13" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP13" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "AND" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::AND" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH21" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH21" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH16" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH16" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "TSTORE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::TSTORE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "TLOAD" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::TLOAD" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DIFFICULTY" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::DIFFICULTY" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP5" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP5" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP11" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP11" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CALLF" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::CALLF" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "MUL" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::MUL" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SHL" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SHL" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH6" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH6" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "GASLIMIT" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::GASLIMIT" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH28" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH28" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CREATE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::CREATE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CALLVALUE" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::CALLVALUE" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "DATALOAD" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DATALOAD" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH4" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH4" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "RETURNCONTRACT" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::RETURNCONTRACT" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "JUMPF" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::JUMPF" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DATACOPY" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DATACOPY" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "KECCAK256" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::KECCAK256" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "RJUMPV" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::RJUMPV" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "BYTE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::BYTE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SGT" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SGT" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "RETF" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::RETF" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH22" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH22" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "MSIZE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::MSIZE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP14" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP14" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "REVERT" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::REVERT" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "MSTORE8" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::MSTORE8" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH5" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH5" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SUB" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SUB" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP5" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP5" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH32" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH32" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP11" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP11" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SHR" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SHR" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP3" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP3" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "NUMBER" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::NUMBER" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PC" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PC" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH8" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH8" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH0" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH0" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "MSTORE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::MSTORE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP16" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP16" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "BALANCE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::BALANCE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "ADD" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::ADD" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH19" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH19" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "STOP" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::STOP" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "BLOBBASEFEE" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::BLOBBASEFEE" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "GT" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::GT" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DIV" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DIV" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH26" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH26" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "NOT" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::NOT" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "OR" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::OR" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "ADDRESS" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::ADDRESS" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAPN" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAPN" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SAR" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SAR" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CALLDATASIZE" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::CALLDATASIZE" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "DELEGATECALL" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::DELEGATECALL" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "EXFCALL" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::EXFCALL" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH18" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH18" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CODESIZE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::CODESIZE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP13" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP13" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP12" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP12" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SIGNEXTEND" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::SIGNEXTEND" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "CALLCODE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::CALLCODE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP7" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP7" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "XOR" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::XOR" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SLT" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SLT" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "CODECOPY" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::CODECOPY" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "LOG4" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::LOG4" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "COINBASE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::COINBASE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH1" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH1" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "STATICCALL" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::STATICCALL" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "LOG2" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::LOG2" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SSTORE" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SSTORE" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "RETURNDATASIZE" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::RETURNDATASIZE" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP9" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP9" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "DUP4" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::DUP4" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "EXP" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::EXP" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SELFBALANCE" |); + M.read (| + M.get_constant (| "revm_interpreter::opcode::SELFBALANCE" |) + |) + ]; + Value.Tuple + [ + M.read (| Value.String "PUSH24" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::PUSH24" |) |) + ]; + Value.Tuple + [ + M.read (| Value.String "SWAP8" |); + M.read (| M.get_constant (| "revm_interpreter::opcode::SWAP8" |) |) + ] + ] + |))) + ] + |) + |))). + + (* + pub const fn instruction(opcode: u8) -> Instruction { + match opcode { + $($name => $f,)* + _ => control::unknown, + } + } + *) + Definition instruction (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H; SPEC ], [ opcode ] => + ltac:(M.monadic + (let opcode := M.alloc (| opcode |) in + M.read (| + M.match_operator (| + opcode, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 0 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::control::stop", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 1 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::add", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 2 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::mul", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 3 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::sub", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 4 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::div", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 5 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::sdiv", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 6 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::rem", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 7 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::smod", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 8 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::addmod", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 9 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::mulmod", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 10 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::exp", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 11 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::arithmetic::signextend", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 16 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::bitwise::lt", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 17 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::bitwise::gt", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 18 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::bitwise::slt", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 19 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::bitwise::sgt", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 20 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::bitwise::eq", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 21 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::bitwise::iszero", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 22 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::bitwise::bitand", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 23 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::bitwise::bitor", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 24 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::bitwise::bitxor", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 25 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::bitwise::not", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 26 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::bitwise::byte", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 27 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::bitwise::shl", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 28 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::bitwise::shr", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 29 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::bitwise::sar", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 32 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::keccak256", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 48 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::address", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 49 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::balance", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 50 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::origin", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 51 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::system::caller", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 52 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::callvalue", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 53 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::calldataload", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 54 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::calldatasize", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 55 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::calldatacopy", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 56 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::codesize", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 57 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::codecopy", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 58 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::gasprice", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 59 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::extcodesize", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 60 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::extcodecopy", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 61 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::returndatasize", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 62 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::returndatacopy", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 63 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::extcodehash", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 64 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::blockhash", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 65 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::coinbase", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 66 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::timestamp", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 67 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::block_number", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 68 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::difficulty", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 69 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::gaslimit", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 70 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::chainid", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 71 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::selfbalance", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 72 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::basefee", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 73 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::blob_hash", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 74 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host_env::blob_basefee", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 80 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::pop", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 81 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::memory::mload", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 82 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::memory::mstore", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 83 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::memory::mstore8", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 84 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::sload", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 85 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::sstore", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 86 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::control::jump", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 87 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::control::jumpi", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 88 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::control::pc", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 89 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::memory::msize", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 90 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::system::gas", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 91 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::control::jumpdest_or_nop", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 92 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::tload", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 93 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::tstore", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 94 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::memory::mcopy", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 95 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::stack::push0", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 96 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 97 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 98 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 99 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 100 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 101 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 102 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 103 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 104 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 105 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 106 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 107 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 108 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 109 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 110 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 111 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 112 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 113 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 114 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 115 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 116 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 117 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 118 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 119 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 120 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 121 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 122 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 123 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 124 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 125 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 126 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 127 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::push", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 128 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 129 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 130 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 131 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 132 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 133 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 134 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 135 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 136 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 137 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 138 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 139 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 140 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 141 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 142 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 143 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dup", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 144 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 145 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 146 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 147 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 148 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 149 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 150 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 151 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 152 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 153 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 154 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 155 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 156 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 157 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 158 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 159 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swap", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 160 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::host::log", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 161 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::host::log", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 162 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::host::log", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 163 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::host::log", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 164 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::host::log", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 208 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::data::data_load", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 209 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::data::data_loadn", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 210 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::data::data_size", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 211 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::data::data_copy", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 224 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::control::rjump", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 225 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::control::rjumpi", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 226 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::control::rjumpv", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 227 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::control::callf", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 228 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::control::retf", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 229 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::control::jumpf", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 230 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::dupn", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 231 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::stack::swapn", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 232 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::stack::exchange", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 236 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::eofcreate", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 237 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::txcreate", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 238 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::return_contract", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 240 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::create", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 241 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::call", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 242 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::call_code", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 243 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_interpreter::instructions::control::ret", [ H ] |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 244 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::delegate_call", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 245 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::create", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 247 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::system::returndataload", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 248 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::extcall", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 249 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::extdcall", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 250 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::static_call", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 251 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::contract::extscall", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 253 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::control::revert", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 254 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::control::invalid", + [ H ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 255 |) in + M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::host::selfdestruct", + [ H; SPEC ] + |)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| + "revm_interpreter::instructions::control::unknown", + [ H ] + |)) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_instruction : M.IsFunction "revm_interpreter::opcode::instruction" instruction. +End opcode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/opcode/eof_printer.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/opcode/eof_printer.md new file mode 100644 index 00000000..0882b9b6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/interpreter/opcode/eof_printer.md @@ -0,0 +1,974 @@ +# ๐Ÿ“ eof_printer.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/interpreter/opcode/eof_printer.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module opcode. + Module eof_printer. + (* + pub fn print_eof_code(code: &[u8]) { + use super::*; + use crate::instructions::utility::read_i16; + use revm_primitives::hex; + + // We can check validity and jump destinations in one pass. + let mut i = 0; + while i < code.len() { + let op = code[i]; + let opcode = &OPCODE_INFO_JUMPTABLE[op as usize]; + + let Some(opcode) = opcode else { + println!("Unknown opcode: 0x{:02X}", op); + i += 1; + continue; + }; + + if opcode.immediate_size() != 0 { + // check if the opcode immediate are within the bounds of the code + if i + opcode.immediate_size() as usize >= code.len() { + println!("Malformed code: immediate out of bounds"); + break; + } + } + + print!("{}", opcode.name()); + if opcode.immediate_size() != 0 { + print!( + " : 0x{:}", + hex::encode(&code[i + 1..i + 1 + opcode.immediate_size() as usize]) + ); + } + + let mut rjumpv_additional_immediates = 0; + if op == RJUMPV { + let max_index = code[i + 1] as usize; + let len = max_index + 1; + // and max_index+1 is to get size of vtable as index starts from 0. + rjumpv_additional_immediates = len * 2; + + // +1 is for max_index byte + if i + 1 + rjumpv_additional_immediates >= code.len() { + println!("Malformed code: immediate out of bounds"); + break; + } + + for vtablei in 0..len { + let offset = unsafe { read_i16(code.as_ptr().add(i + 2 + 2 * vtablei)) } as isize; + println!("RJUMPV[{vtablei}]: 0x{offset:04X}({offset})"); + } + } + + i += 1 + opcode.immediate_size() as usize + rjumpv_additional_immediates; + } + } + *) + Definition print_eof_code (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ code ] => + ltac:(M.monadic + (let code := M.alloc (| code |) in + M.read (| + let~ i := M.alloc (| Value.Integer 0 |) in + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.read (| i |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| code |) ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ op := + M.copy (| M.SubPointer.get_array_field (| M.read (| code |), i |) |) in + let~ opcode := + M.alloc (| + M.SubPointer.get_array_field (| + M.get_constant (| + "revm_interpreter::opcode::OPCODE_INFO_JUMPTABLE" + |), + M.alloc (| M.rust_cast (M.read (| op |)) |) + |) + |) in + M.match_operator (| + opcode, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let opcode := M.alloc (| ฮณ1_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ M.read (| opcode |) ] + |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ge + (BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ M.read (| opcode |) ] + |)))) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| code |) ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "std::io::stdio::_print", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "Malformed code: immediate out of bounds +" + |) + ] + |)) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + M.break (||) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| "std::io::stdio::_print", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array [ M.read (| Value.String "" |) ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.apply (Ty.path "&") [ Ty.path "str" ] + ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "name", + [] + |), + [ M.read (| opcode |) ] + |) + |) + ] + |) + ] + |)) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ M.read (| opcode |) ] + |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| "std::io::stdio::_print", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String " : 0x" |) ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_display", + [ + Ty.path + "alloc::string::String" + ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_function (| + "const_hex::encode", + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path + "core::ops::range::Range") + [ Ty.path "usize" + ] + ], + "index", + [] + |), + [ + M.read (| code |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", + BinOp.Wrap.add + Integer.Usize + (M.read (| + i + |)) + (Value.Integer + 1)); + ("end_", + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| + i + |)) + (Value.Integer + 1)) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ + M.read (| + opcode + |) + ] + |)))) + ] + ] + |) + ] + |) + |) + ] + |) + ] + |)) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ rjumpv_additional_immediates := + M.alloc (| Value.Integer 0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| op |)) + (M.read (| + M.get_constant (| + "revm_interpreter::opcode::RJUMPV" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ max_index := + M.alloc (| + M.rust_cast + (M.read (| + M.SubPointer.get_array_field (| + M.read (| code |), + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1) + |) + |) + |)) + |) in + let~ len := + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| max_index |)) + (Value.Integer 1) + |) in + let~ _ := + M.write (| + rjumpv_additional_immediates, + BinOp.Wrap.mul + Integer.Usize + (M.read (| len |)) + (Value.Integer 2) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ge + (BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 1)) + (M.read (| + rjumpv_additional_immediates + |))) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| code |) ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "std::io::stdio::_print", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "Malformed code: immediate out of bounds +" + |) + ] + |)) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + M.break (||) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", M.read (| len |)) + ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.break (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let vtablei := + M.copy (| ฮณ0_0 |) in + let~ offset := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_function (| + "revm_interpreter::instructions::utility::read_i16", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "*const") + [ Ty.path "u8" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "slice") + [ Ty.path "u8" + ], + "as_ptr", + [] + |), + [ + M.read (| + code + |) + ] + |); + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer + 2)) + (BinOp.Wrap.mul + Integer.Usize + (Value.Integer + 2) + (M.read (| + vtablei + |))) + ] + |) + ] + |)) + |) in + let~ _ := + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "std::io::stdio::_print", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::Arguments", + "new_v1_formatted", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "RJUMPV[" + |); + M.read (| + Value.String + "]: 0x" + |); + M.read (| + Value.String + "(" + |); + M.read (| + Value.String + ") +" + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.match_operator (| + M.alloc (| + Value.Tuple + [ + vtablei; + offset + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let + args := + M.copy (| + ฮณ + |) in + M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_display", + [ + Ty.path + "usize" + ] + |), + [ + M.read (| + M.SubPointer.get_tuple_field (| + args, + 0 + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_upper_hex", + [ + Ty.path + "isize" + ] + |), + [ + M.read (| + M.SubPointer.get_tuple_field (| + args, + 1 + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_display", + [ + Ty.path + "isize" + ] + |), + [ + M.read (| + M.SubPointer.get_tuple_field (| + args, + 1 + |) + |) + ] + |) + ] + |))) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer + 0; + Value.UnicodeChar + 32; + Value.StructTuple + "core::fmt::rt::Alignment::Unknown" + []; + Value.Integer + 0; + Value.StructTuple + "core::fmt::rt::Count::Implied" + []; + Value.StructTuple + "core::fmt::rt::Count::Implied" + [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer + 1; + Value.UnicodeChar + 32; + Value.StructTuple + "core::fmt::rt::Alignment::Unknown" + []; + Value.Integer + 8; + Value.StructTuple + "core::fmt::rt::Count::Implied" + []; + Value.StructTuple + "core::fmt::rt::Count::Is" + [ + Value.Integer + 4 + ] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer + 2; + Value.UnicodeChar + 32; + Value.StructTuple + "core::fmt::rt::Alignment::Unknown" + []; + Value.Integer + 0; + Value.StructTuple + "core::fmt::rt::Count::Implied" + []; + Value.StructTuple + "core::fmt::rt::Count::Implied" + [] + ] + |) + ] + |)); + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::UnsafeArg", + "new", + [] + |), + [] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + let ฮฒ := i in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (Value.Integer 1) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCodeInfo", + "immediate_size", + [] + |), + [ M.read (| opcode |) ] + |)))) + (M.read (| rjumpv_additional_immediates |))) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| M.never_to_any (| M.read (| M.break (||) |) |) |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_print_eof_code : + M.IsFunction "revm_interpreter::opcode::eof_printer::print_eof_code" print_eof_code. + End eof_printer. +End opcode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/blake2.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/blake2.md new file mode 100644 index 00000000..3772efae --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/blake2.md @@ -0,0 +1,1946 @@ +# ๐Ÿ“ blake2.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/precompile/blake2.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module blake2. + Definition value_F_ROUND : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 1 |))). + + Definition value_INPUT_LENGTH : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 213 |))). + + Definition value_FUN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 9 ] + |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ReifyFnPointer *) + M.pointer_coercion (M.get_function (| "revm_precompile::blake2::run", [] |)) + ] + ] + |))). + + (* + pub fn run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + let input = &input[..]; + + if input.len() != INPUT_LENGTH { + return Err(Error::Blake2WrongLength); + } + + let f = match input[212] { + 1 => true, + 0 => false, + _ => return Err(Error::Blake2WrongFinalIndicatorFlag), + }; + + // rounds 4 bytes + let rounds = u32::from_be_bytes(input[..4].try_into().unwrap()) as usize; + let gas_used = rounds as u64 * F_ROUND; + if gas_used > gas_limit { + return Err(Error::OutOfGas); + } + + let mut h = [0u64; 8]; + let mut m = [0u64; 16]; + + for (i, pos) in (4..68).step_by(8).enumerate() { + h[i] = u64::from_le_bytes(input[pos..pos + 8].try_into().unwrap()); + } + for (i, pos) in (68..196).step_by(8).enumerate() { + m[i] = u64::from_le_bytes(input[pos..pos + 8].try_into().unwrap()); + } + let t = [ + u64::from_le_bytes(input[196..196 + 8].try_into().unwrap()), + u64::from_le_bytes(input[204..204 + 8].try_into().unwrap()), + ]; + + algo::compress(rounds, &mut h, m, t, f); + + let mut out = [0u8; 64]; + for (i, h) in (0..64).step_by(8).zip(h.iter()) { + out[i..i + 8].copy_from_slice(&h.to_le_bytes()); + } + + Ok((gas_used, out.into())) + } + *) + Definition run (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_limit := M.alloc (| gas_limit |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ input := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.path "core::ops::range::RangeFull" ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + Value.StructTuple "core::ops::range::RangeFull" [] + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| input |) ] + |)) + (M.read (| + M.get_constant (| "revm_precompile::blake2::INPUT_LENGTH" |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Blake2WrongLength" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ f := + M.copy (| + M.match_operator (| + M.SubPointer.get_array_field (| + M.read (| input |), + M.alloc (| Value.Integer 212 |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 1 |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 0 |) in + M.alloc (| Value.Bool false |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Blake2WrongFinalIndicatorFlag" + [] + ] + |) + |) + |) + |))) + ] + |) + |) in + let~ rounds := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_associated_function (| Ty.path "u32", "from_be_bytes", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + "try_into", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", Value.Integer 4) ] + ] + |) + ] + |) + ] + |) + ] + |)) + |) in + let~ gas_used := + M.alloc (| + BinOp.Wrap.mul + Integer.U64 + (M.rust_cast (M.read (| rounds |))) + (M.read (| M.get_constant (| "revm_precompile::blake2::F_ROUND" |) |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt (M.read (| gas_used |)) (M.read (| gas_limit |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ h := M.alloc (| repeat (Value.Integer 0) 8 |) in + let~ m := M.alloc (| repeat (Value.Integer 0) 16 |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::iter::adapters::enumerate::Enumerate") + [ + Ty.apply + (Ty.path "core::iter::adapters::step_by::StepBy") + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ] + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::step_by::StepBy") + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] + ], + [], + "enumerate", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "step_by", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 4); ("end_", Value.Integer 68) ]; + Value.Integer 8 + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::enumerate::Enumerate") + [ + Ty.apply + (Ty.path "core::iter::adapters::step_by::StepBy") + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ] + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let i := M.copy (| ฮณ1_0 |) in + let pos := M.copy (| ฮณ1_1 |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| h, i |), + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "from_le_bytes", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ], + [ + Ty.apply + (Ty.path "array") + [ Ty.path "u8" ] + ], + "try_into", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| pos |)); + ("end_", + BinOp.Wrap.add + Integer.Usize + (M.read (| pos |)) + (Value.Integer 8)) + ] + ] + |) + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::iter::adapters::enumerate::Enumerate") + [ + Ty.apply + (Ty.path "core::iter::adapters::step_by::StepBy") + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ] + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::step_by::StepBy") + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] + ], + [], + "enumerate", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "step_by", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 68); ("end_", Value.Integer 196) ]; + Value.Integer 8 + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::enumerate::Enumerate") + [ + Ty.apply + (Ty.path "core::iter::adapters::step_by::StepBy") + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ] + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let i := M.copy (| ฮณ1_0 |) in + let pos := M.copy (| ฮณ1_1 |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| m, i |), + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "from_le_bytes", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ], + [ + Ty.apply + (Ty.path "array") + [ Ty.path "u8" ] + ], + "try_into", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| pos |)); + ("end_", + BinOp.Wrap.add + Integer.Usize + (M.read (| pos |)) + (Value.Integer 8)) + ] + ] + |) + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ t := + M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "from_le_bytes", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + "try_into", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 196); + ("end_", + BinOp.Wrap.add + Integer.Usize + (Value.Integer 196) + (Value.Integer 8)) + ] + ] + |) + ] + |) + ] + |) + ] + |); + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "from_le_bytes", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + "try_into", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 204); + ("end_", + BinOp.Wrap.add + Integer.Usize + (Value.Integer 204) + (Value.Integer 8)) + ] + ] + |) + ] + |) + ] + |) + ] + |) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::blake2::algo::compress", [] |), + [ M.read (| rounds |); h; M.read (| m |); M.read (| t |); M.read (| f |) ] + |) + |) in + let~ out := M.alloc (| repeat (Value.Integer 0) 64 |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::iter::adapters::zip::Zip") + [ + Ty.apply + (Ty.path "core::iter::adapters::step_by::StepBy") + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] + ]; + Ty.apply (Ty.path "core::slice::iter::Iter") [ Ty.path "u64" ] + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::step_by::StepBy") + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] + ], + [], + "zip", + [ Ty.apply (Ty.path "core::slice::iter::Iter") [ Ty.path "u64" ] ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "step_by", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 0); ("end_", Value.Integer 64) ]; + Value.Integer 8 + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u64" ], + "iter", + [] + |), + [ (* Unsize *) M.pointer_coercion h ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::zip::Zip") + [ + Ty.apply + (Ty.path "core::iter::adapters::step_by::StepBy") + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ]; + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "u64" ] + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let i := M.copy (| ฮณ1_0 |) in + let h := M.copy (| ฮณ1_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + out; + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| i |)); + ("end_", + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 8)) + ] + ] + |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "to_le_bytes", + [] + |), + [ M.read (| M.read (| h |) |) ] + |) + |)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| gas_used |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ M.read (| out |) ] + |) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_run : M.IsFunction "revm_precompile::blake2::run" run. + + Module algo. + Definition value_SIGMA : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.Array + [ + Value.Array + [ + Value.Integer 0; + Value.Integer 1; + Value.Integer 2; + Value.Integer 3; + Value.Integer 4; + Value.Integer 5; + Value.Integer 6; + Value.Integer 7; + Value.Integer 8; + Value.Integer 9; + Value.Integer 10; + Value.Integer 11; + Value.Integer 12; + Value.Integer 13; + Value.Integer 14; + Value.Integer 15 + ]; + Value.Array + [ + Value.Integer 14; + Value.Integer 10; + Value.Integer 4; + Value.Integer 8; + Value.Integer 9; + Value.Integer 15; + Value.Integer 13; + Value.Integer 6; + Value.Integer 1; + Value.Integer 12; + Value.Integer 0; + Value.Integer 2; + Value.Integer 11; + Value.Integer 7; + Value.Integer 5; + Value.Integer 3 + ]; + Value.Array + [ + Value.Integer 11; + Value.Integer 8; + Value.Integer 12; + Value.Integer 0; + Value.Integer 5; + Value.Integer 2; + Value.Integer 15; + Value.Integer 13; + Value.Integer 10; + Value.Integer 14; + Value.Integer 3; + Value.Integer 6; + Value.Integer 7; + Value.Integer 1; + Value.Integer 9; + Value.Integer 4 + ]; + Value.Array + [ + Value.Integer 7; + Value.Integer 9; + Value.Integer 3; + Value.Integer 1; + Value.Integer 13; + Value.Integer 12; + Value.Integer 11; + Value.Integer 14; + Value.Integer 2; + Value.Integer 6; + Value.Integer 5; + Value.Integer 10; + Value.Integer 4; + Value.Integer 0; + Value.Integer 15; + Value.Integer 8 + ]; + Value.Array + [ + Value.Integer 9; + Value.Integer 0; + Value.Integer 5; + Value.Integer 7; + Value.Integer 2; + Value.Integer 4; + Value.Integer 10; + Value.Integer 15; + Value.Integer 14; + Value.Integer 1; + Value.Integer 11; + Value.Integer 12; + Value.Integer 6; + Value.Integer 8; + Value.Integer 3; + Value.Integer 13 + ]; + Value.Array + [ + Value.Integer 2; + Value.Integer 12; + Value.Integer 6; + Value.Integer 10; + Value.Integer 0; + Value.Integer 11; + Value.Integer 8; + Value.Integer 3; + Value.Integer 4; + Value.Integer 13; + Value.Integer 7; + Value.Integer 5; + Value.Integer 15; + Value.Integer 14; + Value.Integer 1; + Value.Integer 9 + ]; + Value.Array + [ + Value.Integer 12; + Value.Integer 5; + Value.Integer 1; + Value.Integer 15; + Value.Integer 14; + Value.Integer 13; + Value.Integer 4; + Value.Integer 10; + Value.Integer 0; + Value.Integer 7; + Value.Integer 6; + Value.Integer 3; + Value.Integer 9; + Value.Integer 2; + Value.Integer 8; + Value.Integer 11 + ]; + Value.Array + [ + Value.Integer 13; + Value.Integer 11; + Value.Integer 7; + Value.Integer 14; + Value.Integer 12; + Value.Integer 1; + Value.Integer 3; + Value.Integer 9; + Value.Integer 5; + Value.Integer 0; + Value.Integer 15; + Value.Integer 4; + Value.Integer 8; + Value.Integer 6; + Value.Integer 2; + Value.Integer 10 + ]; + Value.Array + [ + Value.Integer 6; + Value.Integer 15; + Value.Integer 14; + Value.Integer 9; + Value.Integer 11; + Value.Integer 3; + Value.Integer 0; + Value.Integer 8; + Value.Integer 12; + Value.Integer 2; + Value.Integer 13; + Value.Integer 7; + Value.Integer 1; + Value.Integer 4; + Value.Integer 10; + Value.Integer 5 + ]; + Value.Array + [ + Value.Integer 10; + Value.Integer 2; + Value.Integer 8; + Value.Integer 4; + Value.Integer 7; + Value.Integer 6; + Value.Integer 1; + Value.Integer 5; + Value.Integer 15; + Value.Integer 11; + Value.Integer 9; + Value.Integer 14; + Value.Integer 3; + Value.Integer 12; + Value.Integer 13; + Value.Integer 0 + ] + ] + |))). + + Definition value_IV : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.Array + [ + Value.Integer 7640891576956012808; + Value.Integer 13503953896175478587; + Value.Integer 4354685564936845355; + Value.Integer 11912009170470909681; + Value.Integer 5840696475078001361; + Value.Integer 11170449401992604703; + Value.Integer 2270897969802886507; + Value.Integer 6620516959819538809 + ] + |))). + + (* + pub fn g(v: &mut [u64], a: usize, b: usize, c: usize, d: usize, x: u64, y: u64) { + v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); + v[d] = (v[d] ^ v[a]).rotate_right(32); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(24); + v[a] = v[a].wrapping_add(v[b]).wrapping_add(y); + v[d] = (v[d] ^ v[a]).rotate_right(16); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(63); + } + *) + Definition g (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ v; a; b; c; d; x; y ] => + ltac:(M.monadic + (let v := M.alloc (| v |) in + let a := M.alloc (| a |) in + let b := M.alloc (| b |) in + let c := M.alloc (| c |) in + let d := M.alloc (| d |) in + let x := M.alloc (| x |) in + let y := M.alloc (| y |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_array_field (| M.read (| v |), a |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "wrapping_add", [] |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "wrapping_add", [] |), + [ + M.read (| M.SubPointer.get_array_field (| M.read (| v |), a |) |); + M.read (| M.SubPointer.get_array_field (| M.read (| v |), b |) |) + ] + |); + M.read (| x |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| M.read (| v |), d |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "rotate_right", [] |), + [ + BinOp.Pure.bit_xor + (M.read (| M.SubPointer.get_array_field (| M.read (| v |), d |) |)) + (M.read (| M.SubPointer.get_array_field (| M.read (| v |), a |) |)); + Value.Integer 32 + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| M.read (| v |), c |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "wrapping_add", [] |), + [ + M.read (| M.SubPointer.get_array_field (| M.read (| v |), c |) |); + M.read (| M.SubPointer.get_array_field (| M.read (| v |), d |) |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| M.read (| v |), b |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "rotate_right", [] |), + [ + BinOp.Pure.bit_xor + (M.read (| M.SubPointer.get_array_field (| M.read (| v |), b |) |)) + (M.read (| M.SubPointer.get_array_field (| M.read (| v |), c |) |)); + Value.Integer 24 + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| M.read (| v |), a |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "wrapping_add", [] |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "wrapping_add", [] |), + [ + M.read (| M.SubPointer.get_array_field (| M.read (| v |), a |) |); + M.read (| M.SubPointer.get_array_field (| M.read (| v |), b |) |) + ] + |); + M.read (| y |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| M.read (| v |), d |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "rotate_right", [] |), + [ + BinOp.Pure.bit_xor + (M.read (| M.SubPointer.get_array_field (| M.read (| v |), d |) |)) + (M.read (| M.SubPointer.get_array_field (| M.read (| v |), a |) |)); + Value.Integer 16 + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| M.read (| v |), c |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "wrapping_add", [] |), + [ + M.read (| M.SubPointer.get_array_field (| M.read (| v |), c |) |); + M.read (| M.SubPointer.get_array_field (| M.read (| v |), d |) |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| M.read (| v |), b |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "rotate_right", [] |), + [ + BinOp.Pure.bit_xor + (M.read (| M.SubPointer.get_array_field (| M.read (| v |), b |) |)) + (M.read (| M.SubPointer.get_array_field (| M.read (| v |), c |) |)); + Value.Integer 63 + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_g : M.IsFunction "revm_precompile::blake2::algo::g" g. + + (* + pub fn compress(rounds: usize, h: &mut [u64; 8], m: [u64; 16], t: [u64; 2], f: bool) { + let mut v = [0u64; 16]; + v[..h.len()].copy_from_slice(h); // First half from state. + v[h.len()..].copy_from_slice(&IV); // Second half from IV. + + v[12] ^= t[0]; + v[13] ^= t[1]; + + if f { + v[14] = !v[14] // Invert all bits if the last-block-flag is set. + } + for i in 0..rounds { + // Message word selection permutation for this round. + let s = &SIGMA[i % 10]; + g(&mut v, 0, 4, 8, 12, m[s[0]], m[s[1]]); + g(&mut v, 1, 5, 9, 13, m[s[2]], m[s[3]]); + g(&mut v, 2, 6, 10, 14, m[s[4]], m[s[5]]); + g(&mut v, 3, 7, 11, 15, m[s[6]], m[s[7]]); + + g(&mut v, 0, 5, 10, 15, m[s[8]], m[s[9]]); + g(&mut v, 1, 6, 11, 12, m[s[10]], m[s[11]]); + g(&mut v, 2, 7, 8, 13, m[s[12]], m[s[13]]); + g(&mut v, 3, 4, 9, 14, m[s[14]], m[s[15]]); + } + + for i in 0..8 { + h[i] ^= v[i] ^ v[i + 8]; + } + } + *) + Definition compress (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ rounds; h; m; t; f ] => + ltac:(M.monadic + (let rounds := M.alloc (| rounds |) in + let h := M.alloc (| h |) in + let m := M.alloc (| m |) in + let t := M.alloc (| t |) in + let f := M.alloc (| f |) in + M.read (| + let~ v := M.alloc (| repeat (Value.Integer 0) 16 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u64" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u64" ], + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ], + "index_mut", + [] + |), + [ + v; + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u64" ], + "len", + [] + |), + [ (* Unsize *) M.pointer_coercion (M.read (| h |)) ] + |)) + ] + ] + |); + (* Unsize *) M.pointer_coercion (M.read (| h |)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u64" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u64" ], + [ Ty.apply (Ty.path "core::ops::range::RangeFrom") [ Ty.path "usize" ] ], + "index_mut", + [] + |), + [ + v; + Value.StructRecord + "core::ops::range::RangeFrom" + [ + ("start", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u64" ], + "len", + [] + |), + [ (* Unsize *) M.pointer_coercion (M.read (| h |)) ] + |)) + ] + ] + |); + (* Unsize *) + M.pointer_coercion (M.get_constant (| "revm_precompile::blake2::algo::IV" |)) + ] + |) + |) in + let~ _ := + let ฮฒ := M.SubPointer.get_array_field (| v, M.alloc (| Value.Integer 12 |) |) in + M.write (| + ฮฒ, + BinOp.Pure.bit_xor + (M.read (| ฮฒ |)) + (M.read (| M.SubPointer.get_array_field (| t, M.alloc (| Value.Integer 0 |) |) |)) + |) in + let~ _ := + let ฮฒ := M.SubPointer.get_array_field (| v, M.alloc (| Value.Integer 13 |) |) in + M.write (| + ฮฒ, + BinOp.Pure.bit_xor + (M.read (| ฮฒ |)) + (M.read (| M.SubPointer.get_array_field (| t, M.alloc (| Value.Integer 1 |) |) |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use f in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.write (| + M.SubPointer.get_array_field (| v, M.alloc (| Value.Integer 14 |) |), + UnOp.Pure.not + (M.read (| + M.SubPointer.get_array_field (| v, M.alloc (| Value.Integer 14 |) |) + |)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 0); ("end_", M.read (| rounds |)) ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let i := M.copy (| ฮณ0_0 |) in + let~ s := + M.alloc (| + M.SubPointer.get_array_field (| + M.get_constant (| + "revm_precompile::blake2::algo::SIGMA" + |), + M.alloc (| + BinOp.Wrap.rem + Integer.Usize + (M.read (| i |)) + (Value.Integer 10) + |) + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::blake2::algo::g", + [] + |), + [ + (* Unsize *) M.pointer_coercion v; + Value.Integer 0; + Value.Integer 4; + Value.Integer 8; + Value.Integer 12; + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 0 |) + |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 1 |) + |) + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::blake2::algo::g", + [] + |), + [ + (* Unsize *) M.pointer_coercion v; + Value.Integer 1; + Value.Integer 5; + Value.Integer 9; + Value.Integer 13; + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 2 |) + |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 3 |) + |) + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::blake2::algo::g", + [] + |), + [ + (* Unsize *) M.pointer_coercion v; + Value.Integer 2; + Value.Integer 6; + Value.Integer 10; + Value.Integer 14; + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 4 |) + |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 5 |) + |) + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::blake2::algo::g", + [] + |), + [ + (* Unsize *) M.pointer_coercion v; + Value.Integer 3; + Value.Integer 7; + Value.Integer 11; + Value.Integer 15; + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 6 |) + |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 7 |) + |) + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::blake2::algo::g", + [] + |), + [ + (* Unsize *) M.pointer_coercion v; + Value.Integer 0; + Value.Integer 5; + Value.Integer 10; + Value.Integer 15; + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 8 |) + |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 9 |) + |) + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::blake2::algo::g", + [] + |), + [ + (* Unsize *) M.pointer_coercion v; + Value.Integer 1; + Value.Integer 6; + Value.Integer 11; + Value.Integer 12; + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 10 |) + |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 11 |) + |) + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::blake2::algo::g", + [] + |), + [ + (* Unsize *) M.pointer_coercion v; + Value.Integer 2; + Value.Integer 7; + Value.Integer 8; + Value.Integer 13; + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 12 |) + |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 13 |) + |) + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::blake2::algo::g", + [] + |), + [ + (* Unsize *) M.pointer_coercion v; + Value.Integer 3; + Value.Integer 4; + Value.Integer 9; + Value.Integer 14; + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 14 |) + |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + m, + M.SubPointer.get_array_field (| + M.read (| s |), + M.alloc (| Value.Integer 15 |) + |) + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 0); ("end_", Value.Integer 8) ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| M.never_to_any (| M.read (| M.break (||) |) |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let i := M.copy (| ฮณ0_0 |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_array_field (| M.read (| h |), i |) in + M.write (| + ฮฒ, + BinOp.Pure.bit_xor + (M.read (| ฮฒ |)) + (BinOp.Pure.bit_xor + (M.read (| M.SubPointer.get_array_field (| v, i |) |)) + (M.read (| + M.SubPointer.get_array_field (| + v, + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| i |)) + (Value.Integer 8) + |) + |) + |))) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) + |))) + | _, _ => M.impossible + end. + + Axiom Function_compress : M.IsFunction "revm_precompile::blake2::algo::compress" compress. + End algo. +End blake2. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/bn128.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/bn128.md new file mode 100644 index 00000000..9f6f4084 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/bn128.md @@ -0,0 +1,3477 @@ +# ๐Ÿ“ bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/precompile/bn128.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module bn128. + Module add. + Definition value_ADDRESS : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 6 ] + |) + |))). + + Definition value_ISTANBUL_ADD_GAS_COST : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 150 |))). + + Definition value_ISTANBUL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.read (| M.get_constant (| "revm_precompile::bn128::add::ADDRESS" |) |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ClosureFnPointer(Normal) *) + M.pointer_coercion + (M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let input := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let gas_limit := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm_precompile::bn128::run_add", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::add::ISTANBUL_ADD_GAS_COST" + |) + |); + M.read (| gas_limit |) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end))) + ] + ] + |))). + + Definition value_BYZANTIUM_ADD_GAS_COST : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 500 |))). + + Definition value_BYZANTIUM : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.read (| M.get_constant (| "revm_precompile::bn128::add::ADDRESS" |) |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ClosureFnPointer(Normal) *) + M.pointer_coercion + (M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let input := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let gas_limit := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm_precompile::bn128::run_add", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::add::BYZANTIUM_ADD_GAS_COST" + |) + |); + M.read (| gas_limit |) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end))) + ] + ] + |))). + End add. + + Module mul. + Definition value_ADDRESS : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 7 ] + |) + |))). + + Definition value_ISTANBUL_MUL_GAS_COST : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 6000 |))). + + Definition value_ISTANBUL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.read (| M.get_constant (| "revm_precompile::bn128::mul::ADDRESS" |) |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ClosureFnPointer(Normal) *) + M.pointer_coercion + (M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let input := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let gas_limit := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm_precompile::bn128::run_mul", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::mul::ISTANBUL_MUL_GAS_COST" + |) + |); + M.read (| gas_limit |) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end))) + ] + ] + |))). + + Definition value_BYZANTIUM_MUL_GAS_COST : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 40000 |))). + + Definition value_BYZANTIUM : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.read (| M.get_constant (| "revm_precompile::bn128::mul::ADDRESS" |) |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ClosureFnPointer(Normal) *) + M.pointer_coercion + (M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let input := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let gas_limit := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm_precompile::bn128::run_mul", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::mul::BYZANTIUM_MUL_GAS_COST" + |) + |); + M.read (| gas_limit |) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end))) + ] + ] + |))). + End mul. + + Module pair_. + Definition value_ADDRESS : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 8 ] + |) + |))). + + Definition value_ISTANBUL_PAIR_PER_POINT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 34000 |))). + + Definition value_ISTANBUL_PAIR_BASE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 45000 |))). + + Definition value_ISTANBUL : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.read (| M.get_constant (| "revm_precompile::bn128::pair::ADDRESS" |) |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ClosureFnPointer(Normal) *) + M.pointer_coercion + (M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let input := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let gas_limit := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm_precompile::bn128::run_pair", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::pair::ISTANBUL_PAIR_PER_POINT" + |) + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::pair::ISTANBUL_PAIR_BASE" + |) + |); + M.read (| gas_limit |) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end))) + ] + ] + |))). + + Definition value_BYZANTIUM_PAIR_PER_POINT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 80000 |))). + + Definition value_BYZANTIUM_PAIR_BASE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 100000 |))). + + Definition value_BYZANTIUM : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.read (| M.get_constant (| "revm_precompile::bn128::pair::ADDRESS" |) |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ClosureFnPointer(Normal) *) + M.pointer_coercion + (M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let input := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let gas_limit := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm_precompile::bn128::run_pair", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::pair::BYZANTIUM_PAIR_PER_POINT" + |) + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::pair::BYZANTIUM_PAIR_BASE" + |) + |); + M.read (| gas_limit |) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end))) + ] + ] + |))). + End pair_. + + Definition value_ADD_INPUT_LEN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| BinOp.Wrap.add Integer.Usize (Value.Integer 64) (Value.Integer 64) |))). + + Definition value_MUL_INPUT_LEN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| BinOp.Wrap.add Integer.Usize (Value.Integer 64) (Value.Integer 32) |))). + + Definition value_PAIR_ELEMENT_LEN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| BinOp.Wrap.add Integer.Usize (Value.Integer 64) (Value.Integer 128) |))). + + (* + pub fn read_fq(input: &[u8]) -> Result { + Fq::from_slice(&input[..32]).map_err(|_| Error::Bn128FieldPointNotAMember) + } + *) + Definition read_fq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "substrate_bn::Fq"; Ty.path "substrate_bn::FieldError" ], + "map_err", + [ + Ty.path "revm_primitives::precompile::PrecompileError"; + Ty.function + [ Ty.tuple [ Ty.path "substrate_bn::FieldError" ] ] + (Ty.path "revm_primitives::precompile::PrecompileError") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "substrate_bn::Fq", "from_slice", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord "core::ops::range::RangeTo" [ ("end_", Value.Integer 32) ] + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::precompile::PrecompileError::Bn128FieldPointNotAMember" + [])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_read_fq : M.IsFunction "revm_precompile::bn128::read_fq" read_fq. + + (* + pub fn read_point(input: &[u8]) -> Result { + let px = read_fq(&input[0..32])?; + let py = read_fq(&input[32..64])?; + new_g1_point(px, py) + } + *) + Definition read_point (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ px := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::Fq"; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| "revm_precompile::bn128::read_fq", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 0); ("end_", Value.Integer 32) ] + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::G1"; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ py := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::Fq"; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| "revm_precompile::bn128::read_fq", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 32); ("end_", Value.Integer 64) ] + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::G1"; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::bn128::new_g1_point", [] |), + [ M.read (| px |); M.read (| py |) ] + |) + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_read_point : M.IsFunction "revm_precompile::bn128::read_point" read_point. + + (* + pub fn new_g1_point(px: Fq, py: Fq) -> Result { + if px == Fq::zero() && py == Fq::zero() { + Ok(G1::zero()) + } else { + AffineG1::new(px, py) + .map(Into::into) + .map_err(|_| Error::Bn128AffineGFailedToCreate) + } + } + *) + Definition new_g1_point (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ px; py ] => + ltac:(M.monadic + (let px := M.alloc (| px |) in + let py := M.alloc (| py |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "substrate_bn::Fq", + [ Ty.path "substrate_bn::Fq" ], + "eq", + [] + |), + [ + px; + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Fq", + "zero", + [] + |), + [] + |) + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "substrate_bn::Fq", + [ Ty.path "substrate_bn::Fq" ], + "eq", + [] + |), + [ + py; + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Fq", + "zero", + [] + |), + [] + |) + |) + ] + |))) + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "substrate_bn::Group", + Ty.path "substrate_bn::G1", + [], + "zero", + [] + |), + [] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "substrate_bn::G1"; Ty.path "substrate_bn::groups::Error" ], + "map_err", + [ + Ty.path "revm_primitives::precompile::PrecompileError"; + Ty.function + [ Ty.tuple [ Ty.path "substrate_bn::groups::Error" ] ] + (Ty.path "revm_primitives::precompile::PrecompileError") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::AffineG1"; + Ty.path "substrate_bn::groups::Error" + ], + "map", + [ + Ty.path "substrate_bn::G1"; + Ty.function + [ Ty.path "substrate_bn::AffineG1" ] + (Ty.path "substrate_bn::G1") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::AffineG1", + "new", + [] + |), + [ M.read (| px |); M.read (| py |) ] + |); + M.get_trait_method (| + "core::convert::Into", + Ty.path "substrate_bn::AffineG1", + [ Ty.path "substrate_bn::G1" ], + "into", + [] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::precompile::PrecompileError::Bn128AffineGFailedToCreate" + [])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_new_g1_point : M.IsFunction "revm_precompile::bn128::new_g1_point" new_g1_point. + + (* + pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { + if gas_cost > gas_limit { + return Err(Error::OutOfGas); + } + + let input = right_pad::(input); + + let p1 = read_point(&input[..64])?; + let p2 = read_point(&input[64..])?; + + let mut output = [0u8; 64]; + if let Some(sum) = AffineG1::from_jacobian(p1 + p2) { + sum.x().to_big_endian(&mut output[..32]).unwrap(); + sum.y().to_big_endian(&mut output[32..]).unwrap(); + } + Ok((gas_cost, output.into())) + } + *) + Definition run_add (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_cost; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_cost := M.alloc (| gas_cost |) in + let gas_limit := M.alloc (| gas_limit |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt (M.read (| gas_cost |)) (M.read (| gas_limit |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ input := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::utilities::right_pad", [] |), + [ M.read (| input |) ] + |) + |) in + let~ p1 := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::G1"; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| "revm_precompile::bn128::read_point", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "deref", + [] + |), + [ input ] + |); + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", Value.Integer 64) ] + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bytes_::Bytes" + ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ p2 := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::G1"; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| "revm_precompile::bn128::read_point", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeFrom") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "deref", + [] + |), + [ input ] + |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", Value.Integer 64) ] + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bytes_::Bytes" + ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ output := M.alloc (| repeat (Value.Integer 0) 64 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::AffineG1", + "from_jacobian", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Add", + Ty.path "substrate_bn::G1", + [ Ty.path "substrate_bn::G1" ], + "add", + [] + |), + [ M.read (| p1 |); M.read (| p2 |) ] + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let sum := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.path "substrate_bn::FieldError" ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Fq", + "to_big_endian", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::AffineG1", + "x", + [] + |), + [ sum ] + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + output; + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", Value.Integer 32) ] + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.path "substrate_bn::FieldError" ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Fq", + "to_big_endian", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::AffineG1", + "y", + [] + |), + [ sum ] + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeFrom") + [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + output; + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", Value.Integer 32) ] + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| gas_cost |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ M.read (| output |) ] + |) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_run_add : M.IsFunction "revm_precompile::bn128::run_add" run_add. + + (* + pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { + if gas_cost > gas_limit { + return Err(Error::OutOfGas); + } + + let input = right_pad::(input); + + let p = read_point(&input[..64])?; + + // `Fr::from_slice` can only fail when the length is not 32. + let fr = bn::Fr::from_slice(&input[64..96]).unwrap(); + + let mut output = [0u8; 64]; + if let Some(mul) = AffineG1::from_jacobian(p * fr) { + mul.x().to_big_endian(&mut output[..32]).unwrap(); + mul.y().to_big_endian(&mut output[32..]).unwrap(); + } + Ok((gas_cost, output.into())) + } + *) + Definition run_mul (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_cost; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_cost := M.alloc (| gas_cost |) in + let gas_limit := M.alloc (| gas_limit |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt (M.read (| gas_cost |)) (M.read (| gas_limit |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ input := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::utilities::right_pad", [] |), + [ M.read (| input |) ] + |) + |) in + let~ p := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::G1"; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| "revm_precompile::bn128::read_point", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "deref", + [] + |), + [ input ] + |); + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", Value.Integer 64) ] + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bytes_::Bytes" + ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ fr := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "substrate_bn::Fr"; Ty.path "substrate_bn::FieldError" ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Fr", + "from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "deref", + [] + |), + [ input ] + |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 64); ("end_", Value.Integer 96) ] + ] + |) + ] + |) + ] + |) + |) in + let~ output := M.alloc (| repeat (Value.Integer 0) 64 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::AffineG1", + "from_jacobian", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Mul", + Ty.path "substrate_bn::G1", + [ Ty.path "substrate_bn::Fr" ], + "mul", + [] + |), + [ M.read (| p |); M.read (| fr |) ] + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let mul := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.path "substrate_bn::FieldError" ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Fq", + "to_big_endian", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::AffineG1", + "x", + [] + |), + [ mul ] + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + output; + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", Value.Integer 32) ] + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.path "substrate_bn::FieldError" ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Fq", + "to_big_endian", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::AffineG1", + "y", + [] + |), + [ mul ] + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeFrom") + [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + output; + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", Value.Integer 32) ] + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| gas_cost |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ M.read (| output |) ] + |) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_run_mul : M.IsFunction "revm_precompile::bn128::run_mul" run_mul. + + (* + pub fn run_pair( + input: &[u8], + pair_per_point_cost: u64, + pair_base_cost: u64, + gas_limit: u64, + ) -> PrecompileResult { + let gas_used = (input.len() / PAIR_ELEMENT_LEN) as u64 * pair_per_point_cost + pair_base_cost; + if gas_used > gas_limit { + return Err(Error::OutOfGas); + } + + if input.len() % PAIR_ELEMENT_LEN != 0 { + return Err(Error::Bn128PairLength); + } + + let success = if input.is_empty() { + true + } else { + let elements = input.len() / PAIR_ELEMENT_LEN; + + let mut mul = Gt::one(); + for idx in 0..elements { + let read_fq_at = |n: usize| { + debug_assert!(n < PAIR_ELEMENT_LEN / 32); + let start = idx * PAIR_ELEMENT_LEN + n * 32; + // SAFETY: We're reading `6 * 32 == PAIR_ELEMENT_LEN` bytes from `input[idx..]` + // per iteration. This is guaranteed to be in-bounds. + let slice = unsafe { input.get_unchecked(start..start + 32) }; + Fq::from_slice(slice).map_err(|_| Error::Bn128FieldPointNotAMember) + }; + let ax = read_fq_at(0)?; + let ay = read_fq_at(1)?; + let bay = read_fq_at(2)?; + let bax = read_fq_at(3)?; + let bby = read_fq_at(4)?; + let bbx = read_fq_at(5)?; + + let a = new_g1_point(ax, ay)?; + let b = { + let ba = Fq2::new(bax, bay); + let bb = Fq2::new(bbx, bby); + if ba.is_zero() && bb.is_zero() { + G2::zero() + } else { + G2::from(AffineG2::new(ba, bb).map_err(|_| Error::Bn128AffineGFailedToCreate)?) + } + }; + + mul = mul * bn::pairing(a, b); + } + + mul == Gt::one() + }; + Ok((gas_used, bool_to_bytes32(success))) + } + *) + Definition run_pair (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; pair_per_point_cost; pair_base_cost; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let pair_per_point_cost := M.alloc (| pair_per_point_cost |) in + let pair_base_cost := M.alloc (| pair_base_cost |) in + let gas_limit := M.alloc (| gas_limit |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ gas_used := + M.alloc (| + BinOp.Wrap.add + Integer.U64 + (BinOp.Wrap.mul + Integer.U64 + (M.rust_cast + (BinOp.Wrap.div + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| input |) ] + |)) + (M.read (| + M.get_constant (| "revm_precompile::bn128::PAIR_ELEMENT_LEN" |) + |)))) + (M.read (| pair_per_point_cost |))) + (M.read (| pair_base_cost |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt (M.read (| gas_used |)) (M.read (| gas_limit |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (BinOp.Wrap.rem + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| input |) ] + |)) + (M.read (| + M.get_constant (| "revm_precompile::bn128::PAIR_ELEMENT_LEN" |) + |))) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Bn128PairLength" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ success := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "is_empty", + [] + |), + [ M.read (| input |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => + ltac:(M.monadic + (let~ elements := + M.alloc (| + BinOp.Wrap.div + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| input |) ] + |)) + (M.read (| + M.get_constant (| "revm_precompile::bn128::PAIR_ELEMENT_LEN" |) + |)) + |) in + let~ mul := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Gt", + "one", + [] + |), + [] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", M.read (| elements |)) + ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let idx := M.copy (| ฮณ0_0 |) in + let~ read_fq_at := + M.alloc (| + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let n := M.copy (| ฮณ |) in + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + Value.Bool + true + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Bool + true + |) in + let~ _ := + M.match_operator (| + M.alloc (| + Value.Tuple + [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let + ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (BinOp.Pure.lt + (M.read (| + n + |)) + (BinOp.Wrap.div + Integer.Usize + (M.read (| + M.get_constant (| + "revm_precompile::bn128::PAIR_ELEMENT_LEN" + |) + |)) + (Value.Integer + 32))) + |)) in + let + _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Bool + true + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic", + [] + |), + [ + M.read (| + Value.String + "assertion failed: n < PAIR_ELEMENT_LEN / 32" + |) + ] + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple + [] + |))) + ] + |) in + M.alloc (| + Value.Tuple [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + let~ start := + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.mul + Integer.Usize + (M.read (| idx |)) + (M.read (| + M.get_constant (| + "revm_precompile::bn128::PAIR_ELEMENT_LEN" + |) + |))) + (BinOp.Wrap.mul + Integer.Usize + (M.read (| n |)) + (Value.Integer + 32)) + |) in + let~ slice := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "slice") + [ Ty.path "u8" + ], + "get_unchecked", + [ + Ty.apply + (Ty.path + "core::ops::range::Range") + [ + Ty.path + "usize" + ] + ] + |), + [ + M.read (| + input + |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", + M.read (| + start + |)); + ("end_", + BinOp.Wrap.add + Integer.Usize + (M.read (| + start + |)) + (Value.Integer + 32)) + ] + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "substrate_bn::Fq"; + Ty.path + "substrate_bn::FieldError" + ], + "map_err", + [ + Ty.path + "revm_primitives::precompile::PrecompileError"; + Ty.function + [ + Ty.tuple + [ + Ty.path + "substrate_bn::FieldError" + ] + ] + (Ty.path + "revm_primitives::precompile::PrecompileError") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "substrate_bn::Fq", + "from_slice", + [] + |), + [ + M.read (| + slice + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| + ฮฑ0 + |), + [ + fun ฮณ => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::precompile::PrecompileError::Bn128FieldPointNotAMember" + [])) + ] + |) + | _ => + M.impossible (||) + end)) + ] + |) + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + |) in + let~ ax := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ Ty.tuple [ Ty.path "usize" ] + ] + (Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ]), + [ Ty.tuple [ Ty.path "usize" ] + ], + "call", + [] + |), + [ + read_fq_at; + Value.Tuple [ Value.Integer 0 ] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bytes_::Bytes" + ]; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ ay := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ Ty.tuple [ Ty.path "usize" ] + ] + (Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ]), + [ Ty.tuple [ Ty.path "usize" ] + ], + "call", + [] + |), + [ + read_fq_at; + Value.Tuple [ Value.Integer 1 ] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bytes_::Bytes" + ]; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ bay := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ Ty.tuple [ Ty.path "usize" ] + ] + (Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ]), + [ Ty.tuple [ Ty.path "usize" ] + ], + "call", + [] + |), + [ + read_fq_at; + Value.Tuple [ Value.Integer 2 ] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bytes_::Bytes" + ]; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ bax := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ Ty.tuple [ Ty.path "usize" ] + ] + (Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ]), + [ Ty.tuple [ Ty.path "usize" ] + ], + "call", + [] + |), + [ + read_fq_at; + Value.Tuple [ Value.Integer 3 ] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bytes_::Bytes" + ]; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ bby := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ Ty.tuple [ Ty.path "usize" ] + ] + (Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ]), + [ Ty.tuple [ Ty.path "usize" ] + ], + "call", + [] + |), + [ + read_fq_at; + Value.Tuple [ Value.Integer 4 ] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bytes_::Bytes" + ]; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ bbx := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ Ty.tuple [ Ty.path "usize" ] + ] + (Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "substrate_bn::Fq"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ]), + [ Ty.tuple [ Ty.path "usize" ] + ], + "call", + [] + |), + [ + read_fq_at; + Value.Tuple [ Value.Integer 5 ] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bytes_::Bytes" + ]; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ a := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "substrate_bn::G1"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_precompile::bn128::new_g1_point", + [] + |), + [ M.read (| ax |); M.read (| ay |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bytes_::Bytes" + ]; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ b := + M.copy (| + let~ ba := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Fq2", + "new", + [] + |), + [ M.read (| bax |); M.read (| bay |) ] + |) + |) in + let~ bb := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Fq2", + "new", + [] + |), + [ M.read (| bbx |); M.read (| bby |) ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "substrate_bn::Fq2", + "is_zero", + [] + |), + [ ba ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path + "substrate_bn::Fq2", + "is_zero", + [] + |), + [ bb ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "substrate_bn::Group", + Ty.path "substrate_bn::G2", + [], + "zero", + [] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::From", + Ty.path "substrate_bn::G2", + [ + Ty.path + "substrate_bn::AffineG2" + ], + "from", + [] + |), + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "substrate_bn::AffineG2"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "substrate_bn::AffineG2"; + Ty.path + "substrate_bn::groups::Error" + ], + "map_err", + [ + Ty.path + "revm_primitives::precompile::PrecompileError"; + Ty.function + [ + Ty.tuple + [ + Ty.path + "substrate_bn::groups::Error" + ] + ] + (Ty.path + "revm_primitives::precompile::PrecompileError") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "substrate_bn::AffineG2", + "new", + [] + |), + [ + M.read (| + ba + |); + M.read (| + bb + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ + with + | [ ฮฑ0 + ] => + M.match_operator (| + M.alloc (| + ฮฑ0 + |), + [ + fun + ฮณ => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::precompile::PrecompileError::Bn128AffineGFailedToCreate" + [])) + ] + |) + | _ => + M.impossible (||) + end)) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := + M.copy (| + ฮณ0_0 + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "u64"; + Ty.path + "alloy_primitives::bytes_::Bytes" + ]; + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::precompile::PrecompileError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| + ฮณ0_0 + |) in + val)) + ] + |) + |) + ] + |) + |))) + ] + |) + |) in + let~ _ := + M.write (| + mul, + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Mul", + Ty.path "substrate_bn::Gt", + [ Ty.path "substrate_bn::Gt" ], + "mul", + [] + |), + [ + M.read (| mul |); + M.call_closure (| + M.get_function (| + "substrate_bn::pairing", + [] + |), + [ M.read (| a |); M.read (| b |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "substrate_bn::Gt", + [ Ty.path "substrate_bn::Gt" ], + "eq", + [] + |), + [ + mul; + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "substrate_bn::Gt", + "one", + [] + |), + [] + |) + |) + ] + |) + |))) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| gas_used |); + M.call_closure (| + M.get_function (| "revm_precompile::utilities::bool_to_bytes32", [] |), + [ M.read (| success |) ] + |) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_run_pair : M.IsFunction "revm_precompile::bn128::run_pair" run_pair. +End bn128. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/hash.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/hash.md new file mode 100644 index 00000000..5a4e73a7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/hash.md @@ -0,0 +1,476 @@ +# ๐Ÿ“ hash.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/precompile/hash.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module hash. + Definition value_SHA256 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 2 ] + |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ReifyFnPointer *) + M.pointer_coercion (M.get_function (| "revm_precompile::hash::sha256_run", [] |)) + ] + ] + |))). + + Definition value_RIPEMD160 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 3 ] + |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_precompile::hash::ripemd160_run", [] |)) + ] + ] + |))). + + (* + pub fn sha256_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + let cost = calc_linear_cost_u32(input.len(), 60, 12); + if cost > gas_limit { + Err(Error::OutOfGas) + } else { + let output = sha2::Sha256::digest(input); + Ok((cost, output.to_vec().into())) + } + } + *) + Definition sha256_run (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_limit := M.alloc (| gas_limit |) in + M.read (| + let~ cost := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::calc_linear_cost_u32", [] |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "bytes::bytes::Bytes", "len", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + Value.Integer 60; + Value.Integer 12 + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| BinOp.Pure.gt (M.read (| cost |)) (M.read (| gas_limit |)) |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ output := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "digest::digest::Digest", + Ty.apply + (Ty.path "digest::core_api::wrapper::CoreWrapper") + [ + Ty.apply + (Ty.path "digest::core_api::ct_variable::CtVariableCoreWrapper") + [ + Ty.path "sha2::core_api::Sha256VarCore"; + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.path "typenum::uint::UTerm"; + Ty.path "typenum::bit::B1" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "sha2::OidSha256" + ] + ], + [], + "digest", + [ Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ] ] + |), + [ M.read (| input |) ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| cost |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "to_vec", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "generic_array::GenericArray") + [ + Ty.path "u8"; + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.path "typenum::uint::UTerm"; + Ty.path "typenum::bit::B1" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ] + ], + [], + "deref", + [] + |), + [ output ] + |) + ] + |) + ] + |) + ] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_sha256_run : M.IsFunction "revm_precompile::hash::sha256_run" sha256_run. + + (* + pub fn ripemd160_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + let gas_used = calc_linear_cost_u32(input.len(), 600, 120); + if gas_used > gas_limit { + Err(Error::OutOfGas) + } else { + let mut hasher = ripemd::Ripemd160::new(); + hasher.update(input); + + let mut output = [0u8; 32]; + hasher.finalize_into((&mut output[12..]).into()); + Ok((gas_used, output.to_vec().into())) + } + } + *) + Definition ripemd160_run (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_limit := M.alloc (| gas_limit |) in + M.read (| + let~ gas_used := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::calc_linear_cost_u32", [] |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "bytes::bytes::Bytes", "len", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + Value.Integer 600; + Value.Integer 120 + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt (M.read (| gas_used |)) (M.read (| gas_limit |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ hasher := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "digest::digest::Digest", + Ty.apply + (Ty.path "digest::core_api::wrapper::CoreWrapper") + [ Ty.path "ripemd::Ripemd160Core" ], + [], + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "digest::digest::Digest", + Ty.apply + (Ty.path "digest::core_api::wrapper::CoreWrapper") + [ Ty.path "ripemd::Ripemd160Core" ], + [], + "update", + [ Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ] ] + |), + [ hasher; M.read (| input |) ] + |) + |) in + let~ output := M.alloc (| repeat (Value.Integer 0) 32 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "digest::digest::Digest", + Ty.apply + (Ty.path "digest::core_api::wrapper::CoreWrapper") + [ Ty.path "ripemd::Ripemd160Core" ], + [], + "finalize_into", + [] + |), + [ + M.read (| hasher |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "generic_array::GenericArray") + [ + Ty.path "u8"; + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.path "typenum::uint::UTerm"; + Ty.path "typenum::bit::B1" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B1" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ] + ] + ] + ], + "into", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeFrom") + [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + output; + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", Value.Integer 12) ] + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| gas_used |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "to_vec", + [] + |), + [ (* Unsize *) M.pointer_coercion output ] + |) + ] + |) + ] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_ripemd160_run : M.IsFunction "revm_precompile::hash::ripemd160_run" ripemd160_run. +End hash. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/identity.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/identity.md new file mode 100644 index 00000000..b9a310fc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/identity.md @@ -0,0 +1,140 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/precompile/identity.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module identity. + Definition value_FUN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 4 ] + |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_precompile::identity::identity_run", [] |)) + ] + ] + |))). + + Definition value_IDENTITY_BASE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 15 |))). + + Definition value_IDENTITY_PER_WORD : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 3 |))). + + (* + pub fn identity_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + let gas_used = calc_linear_cost_u32(input.len(), IDENTITY_BASE, IDENTITY_PER_WORD); + if gas_used > gas_limit { + return Err(Error::OutOfGas); + } + Ok((gas_used, input.clone())) + } + *) + Definition identity_run (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_limit := M.alloc (| gas_limit |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ gas_used := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::calc_linear_cost_u32", [] |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "bytes::bytes::Bytes", "len", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| M.get_constant (| "revm_precompile::identity::IDENTITY_BASE" |) |); + M.read (| + M.get_constant (| "revm_precompile::identity::IDENTITY_PER_WORD" |) + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt (M.read (| gas_used |)) (M.read (| gas_limit |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| gas_used |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ M.read (| input |) ] + |) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_identity_run : M.IsFunction "revm_precompile::identity::identity_run" identity_run. +End identity. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/kzg_point_evaluation.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/kzg_point_evaluation.md new file mode 100644 index 00000000..306a64b6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/kzg_point_evaluation.md @@ -0,0 +1,846 @@ +# ๐Ÿ“ kzg_point_evaluation.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/precompile/kzg_point_evaluation.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module kzg_point_evaluation. + Definition value_POINT_EVALUATION : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.read (| M.get_constant (| "revm_precompile::kzg_point_evaluation::ADDRESS" |) |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Env" + [ + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_precompile::kzg_point_evaluation::run", [] |)) + ] + ] + |))). + + Definition value_ADDRESS : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 10 ] + |) + |))). + + Definition value_GAS_COST : Value.t := M.run ltac:(M.monadic (M.alloc (| Value.Integer 50000 |))). + + Definition value_VERSIONED_HASH_VERSION_KZG : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 1 |))). + + Definition value_RETURN_VALUE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.get_constant (| "revm_precompile::kzg_point_evaluation::RETURN_VALUE::RES" |) + |))). + + (* + pub fn run(input: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult { + if gas_limit < GAS_COST { + return Err(Error::OutOfGas); + } + + // Verify input length. + if input.len() != 192 { + return Err(Error::BlobInvalidInputLength); + } + + // Verify commitment matches versioned_hash + let versioned_hash = &input[..32]; + let commitment = &input[96..144]; + if kzg_to_versioned_hash(commitment) != versioned_hash { + return Err(Error::BlobMismatchedVersion); + } + + // Verify KZG proof with z and y in big endian format + let commitment = as_bytes48(commitment); + let z = as_bytes32(&input[32..64]); + let y = as_bytes32(&input[64..96]); + let proof = as_bytes48(&input[144..192]); + if !verify_kzg_proof(commitment, z, y, proof, env.cfg.kzg_settings.get()) { + return Err(Error::BlobVerifyKzgProofFailed); + } + + // Return FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded 32 byte big endian values + Ok((GAS_COST, RETURN_VALUE.into())) + } + *) + Definition run (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_limit; env ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_limit := M.alloc (| gas_limit |) in + let env := M.alloc (| env |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.read (| gas_limit |)) + (M.read (| + M.get_constant (| + "revm_precompile::kzg_point_evaluation::GAS_COST" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |)) + (Value.Integer 192) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::BlobInvalidInputLength" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ versioned_hash := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + Value.StructRecord "core::ops::range::RangeTo" [ ("end_", Value.Integer 32) ] + ] + |) + |) in + let~ commitment := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 96); ("end_", Value.Integer 144) ] + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ], + "ne", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::kzg_point_evaluation::kzg_to_versioned_hash", + [] + |), + [ M.read (| commitment |) ] + |) + |); + versioned_hash + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::BlobMismatchedVersion" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ commitment := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::kzg_point_evaluation::as_bytes48", [] |), + [ M.read (| commitment |) ] + |) + |) in + let~ z := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::kzg_point_evaluation::as_bytes32", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 32); ("end_", Value.Integer 64) ] + ] + |) + ] + |) + |) in + let~ y := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::kzg_point_evaluation::as_bytes32", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 64); ("end_", Value.Integer 96) ] + ] + |) + ] + |) + |) in + let~ proof := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::kzg_point_evaluation::as_bytes48", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 144); ("end_", Value.Integer 192) ] + ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_function (| + "revm_precompile::kzg_point_evaluation::verify_kzg_proof", + [] + |), + [ + M.read (| commitment |); + M.read (| z |); + M.read (| y |); + M.read (| proof |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::kzg::env_settings::EnvKzgSettings", + "get", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "cfg" + |), + "revm_primitives::env::CfgEnv", + "kzg_settings" + |) + ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::BlobVerifyKzgProofFailed" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| + M.get_constant (| "revm_precompile::kzg_point_evaluation::GAS_COST" |) + |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_precompile::kzg_point_evaluation::RETURN_VALUE" + |) + |) + ] + |) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_run : M.IsFunction "revm_precompile::kzg_point_evaluation::run" run. + + (* + pub fn kzg_to_versioned_hash(commitment: &[u8]) -> [u8; 32] { + let mut hash: [u8; 32] = Sha256::digest(commitment).into(); + hash[0] = VERSIONED_HASH_VERSION_KZG; + hash + } + *) + Definition kzg_to_versioned_hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ commitment ] => + ltac:(M.monadic + (let commitment := M.alloc (| commitment |) in + M.read (| + let~ hash := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "generic_array::GenericArray") + [ + Ty.path "u8"; + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.path "typenum::uint::UTerm"; + Ty.path "typenum::bit::B1" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ] + ], + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + "into", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "digest::digest::Digest", + Ty.apply + (Ty.path "digest::core_api::wrapper::CoreWrapper") + [ + Ty.apply + (Ty.path "digest::core_api::ct_variable::CtVariableCoreWrapper") + [ + Ty.path "sha2::core_api::Sha256VarCore"; + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.apply + (Ty.path "typenum::uint::UInt") + [ + Ty.path "typenum::uint::UTerm"; + Ty.path "typenum::bit::B1" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "typenum::bit::B0" + ]; + Ty.path "sha2::OidSha256" + ] + ], + [], + "digest", + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] ] + |), + [ M.read (| commitment |) ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_array_field (| hash, M.alloc (| Value.Integer 0 |) |), + M.read (| + M.get_constant (| + "revm_precompile::kzg_point_evaluation::VERSIONED_HASH_VERSION_KZG" + |) + |) + |) in + hash + |))) + | _, _ => M.impossible + end. + + Axiom Function_kzg_to_versioned_hash : + M.IsFunction + "revm_precompile::kzg_point_evaluation::kzg_to_versioned_hash" + kzg_to_versioned_hash. + + (* + pub fn verify_kzg_proof( + commitment: &Bytes48, + z: &Bytes32, + y: &Bytes32, + proof: &Bytes48, + kzg_settings: &KzgSettings, + ) -> bool { + KzgProof::verify_kzg_proof(commitment, z, y, proof, kzg_settings).unwrap_or(false) + } + *) + Definition verify_kzg_proof (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ commitment; z; y; proof; kzg_settings ] => + ltac:(M.monadic + (let commitment := M.alloc (| commitment |) in + let z := M.alloc (| z |) in + let y := M.alloc (| y |) in + let proof := M.alloc (| proof |) in + let kzg_settings := M.alloc (| kzg_settings |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "bool"; Ty.path "c_kzg::bindings::Error" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "c_kzg::bindings::KZGProof", + "verify_kzg_proof", + [] + |), + [ + M.read (| commitment |); + M.read (| z |); + M.read (| y |); + M.read (| proof |); + M.read (| kzg_settings |) + ] + |); + Value.Bool false + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_verify_kzg_proof : + M.IsFunction "revm_precompile::kzg_point_evaluation::verify_kzg_proof" verify_kzg_proof. + + (* + pub fn as_array(bytes: &[u8]) -> &[u8; N] { + bytes.try_into().expect("slice with incorrect length") + } + *) + Definition as_array (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ bytes ] => + ltac:(M.monadic + (let bytes := M.alloc (| bytes |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ]; + Ty.path "core::array::TryFromSliceError" + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] ], + "try_into", + [] + |), + [ M.read (| bytes |) ] + |); + M.read (| Value.String "slice with incorrect length" |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_as_array : M.IsFunction "revm_precompile::kzg_point_evaluation::as_array" as_array. + + (* + pub fn as_bytes32(bytes: &[u8]) -> &Bytes32 { + // SAFETY: `#[repr(C)] Bytes32([u8; 32])` + unsafe { &*as_array::<32>(bytes).as_ptr().cast() } + } + *) + Definition as_bytes32 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ bytes ] => + ltac:(M.monadic + (let bytes := M.alloc (| bytes |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "cast", + [ Ty.path "c_kzg::bindings::Bytes32" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_function (| "revm_precompile::kzg_point_evaluation::as_array", [] |), + [ M.read (| bytes |) ] + |)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_as_bytes32 : + M.IsFunction "revm_precompile::kzg_point_evaluation::as_bytes32" as_bytes32. + + (* + pub fn as_bytes48(bytes: &[u8]) -> &Bytes48 { + // SAFETY: `#[repr(C)] Bytes48([u8; 48])` + unsafe { &*as_array::<48>(bytes).as_ptr().cast() } + } + *) + Definition as_bytes48 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ bytes ] => + ltac:(M.monadic + (let bytes := M.alloc (| bytes |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "cast", + [ Ty.path "c_kzg::bindings::Bytes48" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_function (| "revm_precompile::kzg_point_evaluation::as_array", [] |), + [ M.read (| bytes |) ] + |)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_as_bytes48 : + M.IsFunction "revm_precompile::kzg_point_evaluation::as_bytes48" as_bytes48. +End kzg_point_evaluation. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/lib.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/lib.md new file mode 100644 index 00000000..56928119 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/lib.md @@ -0,0 +1,2753 @@ +# ๐Ÿ“ lib.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/precompile/lib.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +(* +pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { + (len as u64 + 32 - 1) / 32 * word + base +} +*) +Definition calc_linear_cost_u32 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ len; base; word ] => + ltac:(M.monadic + (let len := M.alloc (| len |) in + let base := M.alloc (| base |) in + let word := M.alloc (| word |) in + BinOp.Wrap.add + Integer.U64 + (BinOp.Wrap.mul + Integer.U64 + (BinOp.Wrap.div + Integer.U64 + (BinOp.Wrap.sub + Integer.U64 + (BinOp.Wrap.add Integer.U64 (M.rust_cast (M.read (| len |))) (Value.Integer 32)) + (Value.Integer 1)) + (Value.Integer 32)) + (M.read (| word |))) + (M.read (| base |)))) + | _, _ => M.impossible + end. + +Axiom Function_calc_linear_cost_u32 : + M.IsFunction "revm_precompile::calc_linear_cost_u32" calc_linear_cost_u32. + +(* StructRecord + { + name := "PrecompileOutput"; + ty_params := []; + fields := + [ + ("cost", Ty.path "u64"); + ("output", + Ty.apply (Ty.path "alloc::vec::Vec") [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ]); + ("logs", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + +Module Impl_core_clone_Clone_for_revm_precompile_PrecompileOutput. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileOutput". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_precompile::PrecompileOutput" + [ + ("cost", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u64", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "cost" + |) + ] + |)); + ("output", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "output" + |) + ] + |)); + ("logs", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "logs" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. +End Impl_core_clone_Clone_for_revm_precompile_PrecompileOutput. + +Module Impl_core_fmt_Debug_for_revm_precompile_PrecompileOutput. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileOutput". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "PrecompileOutput" |); + M.read (| Value.String "cost" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "cost" + |)); + M.read (| Value.String "output" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "output" + |)); + M.read (| Value.String "logs" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "logs" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. +End Impl_core_fmt_Debug_for_revm_precompile_PrecompileOutput. + +Module Impl_core_default_Default_for_revm_precompile_PrecompileOutput. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileOutput". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_precompile::PrecompileOutput" + [ + ("cost", + M.call_closure (| + M.get_trait_method (| "core::default::Default", Ty.path "u64", [], "default", [] |), + [] + |)); + ("output", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [], + "default", + [] + |), + [] + |)); + ("logs", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. +End Impl_core_default_Default_for_revm_precompile_PrecompileOutput. + +Module Impl_core_marker_StructuralPartialEq_for_revm_precompile_PrecompileOutput. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileOutput". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. +End Impl_core_marker_StructuralPartialEq_for_revm_precompile_PrecompileOutput. + +Module Impl_core_cmp_PartialEq_for_revm_precompile_PrecompileOutput. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileOutput". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "cost" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_precompile::PrecompileOutput", + "cost" + |) + |)), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "output" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_precompile::PrecompileOutput", + "output" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "logs" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_precompile::PrecompileOutput", + "logs" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. +End Impl_core_cmp_PartialEq_for_revm_precompile_PrecompileOutput. + +Module Impl_core_marker_StructuralEq_for_revm_precompile_PrecompileOutput. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileOutput". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. +End Impl_core_marker_StructuralEq_for_revm_precompile_PrecompileOutput. + +Module Impl_core_cmp_Eq_for_revm_precompile_PrecompileOutput. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileOutput". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. +End Impl_core_cmp_Eq_for_revm_precompile_PrecompileOutput. + +Module Impl_core_hash_Hash_for_revm_precompile_PrecompileOutput. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileOutput". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u64", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "cost" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "output" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::PrecompileOutput", + "logs" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. +End Impl_core_hash_Hash_for_revm_precompile_PrecompileOutput. + +Module Impl_revm_precompile_PrecompileOutput. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileOutput". + + (* + pub fn without_logs(cost: u64, output: Vec) -> Self { + Self { + cost, + output, + logs: Vec::new(), + } + } + *) + Definition without_logs (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ cost; output ] => + ltac:(M.monadic + (let cost := M.alloc (| cost |) in + let output := M.alloc (| output |) in + Value.StructRecord + "revm_precompile::PrecompileOutput" + [ + ("cost", M.read (| cost |)); + ("output", M.read (| output |)); + ("logs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_without_logs : M.IsAssociatedFunction Self "without_logs" without_logs. +End Impl_revm_precompile_PrecompileOutput. + +(* StructRecord + { + name := "Precompiles"; + ty_params := []; + fields := + [ + ("inner", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ]) + ]; + } *) + +Module Impl_core_clone_Clone_for_revm_precompile_Precompiles. + Definition Self : Ty.t := Ty.path "revm_precompile::Precompiles". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_precompile::Precompiles" + [ + ("inner", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::Precompiles", + "inner" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. +End Impl_core_clone_Clone_for_revm_precompile_Precompiles. + +Module Impl_core_default_Default_for_revm_precompile_Precompiles. + Definition Self : Ty.t := Ty.path "revm_precompile::Precompiles". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_precompile::Precompiles" + [ + ("inner", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. +End Impl_core_default_Default_for_revm_precompile_Precompiles. + +Module Impl_core_fmt_Debug_for_revm_precompile_Precompiles. + Definition Self : Ty.t := Ty.path "revm_precompile::Precompiles". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Precompiles" |); + M.read (| Value.String "inner" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::Precompiles", + "inner" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. +End Impl_core_fmt_Debug_for_revm_precompile_Precompiles. + +Module Impl_revm_precompile_Precompiles. + Definition Self : Ty.t := Ty.path "revm_precompile::Precompiles". + + (* + pub fn new(spec: PrecompileSpecId) -> &'static Self { + match spec { + PrecompileSpecId::HOMESTEAD => Self::homestead(), + PrecompileSpecId::BYZANTIUM => Self::byzantium(), + PrecompileSpecId::ISTANBUL => Self::istanbul(), + PrecompileSpecId::BERLIN => Self::berlin(), + PrecompileSpecId::CANCUN => Self::cancun(), + PrecompileSpecId::LATEST => Self::latest(), + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec ] => + ltac:(M.monadic + (let spec := M.alloc (| spec |) in + M.read (| + M.match_operator (| + spec, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::HOMESTEAD" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "homestead", + [] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::BYZANTIUM" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "byzantium", + [] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::ISTANBUL" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "istanbul", + [] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::BERLIN" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "berlin", + [] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::CANCUN" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "cancun", + [] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::LATEST" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "latest", + [] + |), + [] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn homestead() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Precompiles::default(); + precompiles.extend([ + secp256k1::ECRECOVER, + hash::SHA256, + hash::RIPEMD160, + identity::FUN, + ]); + Box::new(precompiles) + }) + } + *) + Definition homestead (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "once_cell::race::once_box::OnceBox") + [ Ty.path "revm_precompile::Precompiles" ], + "get_or_init", + [ + Ty.function + [ Ty.tuple [] ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_precompile::Precompiles"; Ty.path "alloc::alloc::Global" ]) + ] + |), + [ + M.read (| M.get_constant (| "revm_precompile::homestead::INSTANCE" |) |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.read (| + let~ precompiles := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_precompile::Precompiles", + [], + "default", + [] + |), + [] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "extend", + [ + Ty.apply + (Ty.path "array") + [ Ty.path "revm_precompile::PrecompileWithAddress" ] + ] + |), + [ + precompiles; + Value.Array + [ + M.read (| + M.get_constant (| + "revm_precompile::secp256k1::ECRECOVER" + |) + |); + M.read (| + M.get_constant (| "revm_precompile::hash::SHA256" |) + |); + M.read (| + M.get_constant (| "revm_precompile::hash::RIPEMD160" |) + |); + M.read (| + M.get_constant (| "revm_precompile::identity::FUN" |) + |) + ] + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_precompile::Precompiles"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| precompiles |) ] + |) + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_homestead : M.IsAssociatedFunction Self "homestead" homestead. + + (* + pub fn byzantium() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::homestead().clone(); + precompiles.extend([ + // EIP-196: Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. + // EIP-197: Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. + bn128::add::BYZANTIUM, + bn128::mul::BYZANTIUM, + bn128::pair::BYZANTIUM, + // EIP-198: Big integer modular exponentiation. + modexp::BYZANTIUM, + ]); + Box::new(precompiles) + }) + } + *) + Definition byzantium (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "once_cell::race::once_box::OnceBox") + [ Ty.path "revm_precompile::Precompiles" ], + "get_or_init", + [ + Ty.function + [ Ty.tuple [] ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_precompile::Precompiles"; Ty.path "alloc::alloc::Global" ]) + ] + |), + [ + M.read (| M.get_constant (| "revm_precompile::byzantium::INSTANCE" |) |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.read (| + let~ precompiles := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_precompile::Precompiles", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "homestead", + [] + |), + [] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "extend", + [ + Ty.apply + (Ty.path "array") + [ Ty.path "revm_precompile::PrecompileWithAddress" ] + ] + |), + [ + precompiles; + Value.Array + [ + M.read (| + M.get_constant (| + "revm_precompile::bn128::add::BYZANTIUM" + |) + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::mul::BYZANTIUM" + |) + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::pair::BYZANTIUM" + |) + |); + M.read (| + M.get_constant (| + "revm_precompile::modexp::BYZANTIUM" + |) + |) + ] + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_precompile::Precompiles"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| precompiles |) ] + |) + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_byzantium : M.IsAssociatedFunction Self "byzantium" byzantium. + + (* + pub fn istanbul() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::byzantium().clone(); + precompiles.extend([ + // EIP-152: Add BLAKE2 compression function `F` precompile. + blake2::FUN, + // EIP-1108: Reduce alt_bn128 precompile gas costs. + bn128::add::ISTANBUL, + bn128::mul::ISTANBUL, + bn128::pair::ISTANBUL, + ]); + Box::new(precompiles) + }) + } + *) + Definition istanbul (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "once_cell::race::once_box::OnceBox") + [ Ty.path "revm_precompile::Precompiles" ], + "get_or_init", + [ + Ty.function + [ Ty.tuple [] ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_precompile::Precompiles"; Ty.path "alloc::alloc::Global" ]) + ] + |), + [ + M.read (| M.get_constant (| "revm_precompile::istanbul::INSTANCE" |) |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.read (| + let~ precompiles := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_precompile::Precompiles", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "byzantium", + [] + |), + [] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "extend", + [ + Ty.apply + (Ty.path "array") + [ Ty.path "revm_precompile::PrecompileWithAddress" ] + ] + |), + [ + precompiles; + Value.Array + [ + M.read (| + M.get_constant (| "revm_precompile::blake2::FUN" |) + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::add::ISTANBUL" + |) + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::mul::ISTANBUL" + |) + |); + M.read (| + M.get_constant (| + "revm_precompile::bn128::pair::ISTANBUL" + |) + |) + ] + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_precompile::Precompiles"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| precompiles |) ] + |) + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_istanbul : M.IsAssociatedFunction Self "istanbul" istanbul. + + (* + pub fn berlin() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::istanbul().clone(); + precompiles.extend([ + // EIP-2565: ModExp Gas Cost. + modexp::BERLIN, + ]); + Box::new(precompiles) + }) + } + *) + Definition berlin (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "once_cell::race::once_box::OnceBox") + [ Ty.path "revm_precompile::Precompiles" ], + "get_or_init", + [ + Ty.function + [ Ty.tuple [] ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_precompile::Precompiles"; Ty.path "alloc::alloc::Global" ]) + ] + |), + [ + M.read (| M.get_constant (| "revm_precompile::berlin::INSTANCE" |) |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.read (| + let~ precompiles := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_precompile::Precompiles", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "istanbul", + [] + |), + [] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "extend", + [ + Ty.apply + (Ty.path "array") + [ Ty.path "revm_precompile::PrecompileWithAddress" ] + ] + |), + [ + precompiles; + Value.Array + [ + M.read (| + M.get_constant (| "revm_precompile::modexp::BERLIN" |) + |) + ] + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_precompile::Precompiles"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| precompiles |) ] + |) + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_berlin : M.IsAssociatedFunction Self "berlin" berlin. + + (* + pub fn cancun() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let precompiles = Self::berlin().clone(); + + // Don't include KZG point evaluation precompile in no_std builds. + #[cfg(feature = "c-kzg")] + let precompiles = { + let mut precompiles = precompiles; + precompiles.extend([ + // EIP-4844: Shard Blob Transactions + kzg_point_evaluation::POINT_EVALUATION, + ]); + precompiles + }; + + Box::new(precompiles) + }) + } + *) + Definition cancun (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "once_cell::race::once_box::OnceBox") + [ Ty.path "revm_precompile::Precompiles" ], + "get_or_init", + [ + Ty.function + [ Ty.tuple [] ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_precompile::Precompiles"; Ty.path "alloc::alloc::Global" ]) + ] + |), + [ + M.read (| M.get_constant (| "revm_precompile::cancun::INSTANCE" |) |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.read (| + let~ precompiles := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_precompile::Precompiles", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "berlin", + [] + |), + [] + |) + ] + |) + |) in + let~ precompiles := + M.copy (| + let~ precompiles := M.copy (| precompiles |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "extend", + [ + Ty.apply + (Ty.path "array") + [ Ty.path "revm_precompile::PrecompileWithAddress" ] + ] + |), + [ + precompiles; + Value.Array + [ + M.read (| + M.get_constant (| + "revm_precompile::kzg_point_evaluation::POINT_EVALUATION" + |) + |) + ] + ] + |) + |) in + precompiles + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_precompile::Precompiles"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| precompiles |) ] + |) + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_cancun : M.IsAssociatedFunction Self "cancun" cancun. + + (* + pub fn latest() -> &'static Self { + Self::cancun() + } + *) + Definition latest (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| Ty.path "revm_precompile::Precompiles", "cancun", [] |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_latest : M.IsAssociatedFunction Self "latest" latest. + + (* + pub fn addresses(&self) -> impl Iterator { + self.inner.keys() + } + *) + Definition addresses (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + "keys", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::Precompiles", + "inner" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_addresses : M.IsAssociatedFunction Self "addresses" addresses. + + (* + pub fn into_addresses(self) -> impl Iterator { + self.inner.into_keys() + } + *) + Definition into_addresses (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + "into_keys", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm_precompile::Precompiles", + "inner" + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_addresses : + M.IsAssociatedFunction Self "into_addresses" into_addresses. + + (* + pub fn contains(&self, address: &Address) -> bool { + self.inner.contains_key(address) + } + *) + Definition contains (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + "contains_key", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::Precompiles", + "inner" + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_contains : M.IsAssociatedFunction Self "contains" contains. + + (* + pub fn get(&self, address: &Address) -> Option<&Precompile> { + self.inner.get(address) + } + *) + Definition get (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::Precompiles", + "inner" + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get : M.IsAssociatedFunction Self "get" get. + + (* + pub fn get_mut(&mut self, address: &Address) -> Option<&mut Precompile> { + self.inner.get_mut(address) + } + *) + Definition get_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::Precompiles", + "inner" + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get_mut : M.IsAssociatedFunction Self "get_mut" get_mut. + + (* + pub fn is_empty(&self) -> bool { + self.inner.len() == 0 + } + *) + Definition is_empty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::Precompiles", + "inner" + |) + ] + |)) + (Value.Integer 0))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_empty : M.IsAssociatedFunction Self "is_empty" is_empty. + + (* + pub fn len(&self) -> usize { + self.inner.len() + } + *) + Definition len (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::Precompiles", + "inner" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_len : M.IsAssociatedFunction Self "len" len. + + (* + pub fn extend(&mut self, other: impl IntoIterator) { + self.inner.extend(other.into_iter().map(Into::into)); + } + *) + Definition extend (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ impl_IntoIterator_Item___PrecompileWithAddress_ ], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::Extend", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ] + ], + "extend", + [ + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.associated; + Ty.function + [ Ty.path "revm_precompile::PrecompileWithAddress" ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ]) + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_precompile::Precompiles", + "inner" + |); + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "map", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ]; + Ty.function + [ Ty.path "revm_precompile::PrecompileWithAddress" ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + impl_IntoIterator_Item___PrecompileWithAddress_, + [], + "into_iter", + [] + |), + [ M.read (| other |) ] + |); + M.get_trait_method (| + "core::convert::Into", + Ty.path "revm_precompile::PrecompileWithAddress", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ] + ], + "into", + [] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_extend : M.IsAssociatedFunction Self "extend" extend. +End Impl_revm_precompile_Precompiles. + +(* StructTuple + { + name := "PrecompileWithAddress"; + ty_params := []; + fields := + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ]; + } *) + +Module Impl_core_clone_Clone_for_revm_precompile_PrecompileWithAddress. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileWithAddress". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_precompile::PrecompileWithAddress", + 0 + |) + ] + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::precompile::Precompile", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_precompile::PrecompileWithAddress", + 1 + |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. +End Impl_core_clone_Clone_for_revm_precompile_PrecompileWithAddress. + +Module Impl_core_fmt_Debug_for_revm_precompile_PrecompileWithAddress. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileWithAddress". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "PrecompileWithAddress" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_precompile::PrecompileWithAddress", + 0 + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_precompile::PrecompileWithAddress", + 1 + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. +End Impl_core_fmt_Debug_for_revm_precompile_PrecompileWithAddress. + +Module Impl_core_convert_From_Tuple_alloy_primitives_bits_address_Address_revm_primitives_precompile_Precompile__for_revm_precompile_PrecompileWithAddress. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileWithAddress". + + (* + fn from(value: (Address, Precompile)) -> Self { + PrecompileWithAddress(value.0, value.1) + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.read (| M.SubPointer.get_tuple_field (| value, 0 |) |); + M.read (| M.SubPointer.get_tuple_field (| value, 1 |) |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ + (* T *) + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ] + ] + (* Instance *) [ ("from", InstanceField.Method from) ]. +End Impl_core_convert_From_Tuple_alloy_primitives_bits_address_Address_revm_primitives_precompile_Precompile__for_revm_precompile_PrecompileWithAddress. + +Module Impl_core_convert_From_revm_precompile_PrecompileWithAddress_for_Tuple_alloy_primitives_bits_address_Address_revm_primitives_precompile_Precompile_. + Definition Self : Ty.t := + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ]. + + (* + fn from(value: PrecompileWithAddress) -> Self { + (value.0, value.1) + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + Value.Tuple + [ + M.read (| + M.SubPointer.get_struct_tuple_field (| + value, + "revm_precompile::PrecompileWithAddress", + 0 + |) + |); + M.read (| + M.SubPointer.get_struct_tuple_field (| + value, + "revm_precompile::PrecompileWithAddress", + 1 + |) + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) [ (* T *) Ty.path "revm_precompile::PrecompileWithAddress" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. +End Impl_core_convert_From_revm_precompile_PrecompileWithAddress_for_Tuple_alloy_primitives_bits_address_Address_revm_primitives_precompile_Precompile_. + +(* +Enum PrecompileSpecId +{ + ty_params := []; + variants := + [ + { + name := "HOMESTEAD"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BYZANTIUM"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ISTANBUL"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BERLIN"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CANCUN"; + item := StructTuple []; + discriminant := None; + }; + { + name := "LATEST"; + item := StructTuple []; + discriminant := None; + } + ]; +} +*) + +Module Impl_core_marker_Copy_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + Axiom Implements : + M.IsTraitInstance "core::marker::Copy" Self (* Trait polymorphic types *) [] (* Instance *) []. +End Impl_core_marker_Copy_for_revm_precompile_PrecompileSpecId. + +Module Impl_core_clone_Clone_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. +End Impl_core_clone_Clone_for_revm_precompile_PrecompileSpecId. + +Module Impl_core_fmt_Debug_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::HOMESTEAD" |) in + M.alloc (| M.read (| Value.String "HOMESTEAD" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::BYZANTIUM" |) in + M.alloc (| M.read (| Value.String "BYZANTIUM" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::ISTANBUL" |) in + M.alloc (| M.read (| Value.String "ISTANBUL" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::BERLIN" |) in + M.alloc (| M.read (| Value.String "BERLIN" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::CANCUN" |) in + M.alloc (| M.read (| Value.String "CANCUN" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_precompile::PrecompileSpecId::LATEST" |) in + M.alloc (| M.read (| Value.String "LATEST" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. +End Impl_core_fmt_Debug_for_revm_precompile_PrecompileSpecId. + +Module Impl_core_marker_StructuralPartialEq_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. +End Impl_core_marker_StructuralPartialEq_for_revm_precompile_PrecompileSpecId. + +Module Impl_core_cmp_PartialEq_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_precompile::PrecompileSpecId" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_precompile::PrecompileSpecId" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. +End Impl_core_cmp_PartialEq_for_revm_precompile_PrecompileSpecId. + +Module Impl_core_marker_StructuralEq_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. +End Impl_core_marker_StructuralEq_for_revm_precompile_PrecompileSpecId. + +Module Impl_core_cmp_Eq_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. +End Impl_core_cmp_Eq_for_revm_precompile_PrecompileSpecId. + +Module Impl_core_hash_Hash_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_precompile::PrecompileSpecId" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. +End Impl_core_hash_Hash_for_revm_precompile_PrecompileSpecId. + +Module Impl_core_cmp_Ord_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_precompile::PrecompileSpecId" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_precompile::PrecompileSpecId" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "isize", [], "cmp", [] |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. +End Impl_core_cmp_Ord_for_revm_precompile_PrecompileSpecId. + +Module Impl_core_cmp_PartialOrd_for_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_precompile::PrecompileSpecId" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_precompile::PrecompileSpecId" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "isize", + [ Ty.path "isize" ], + "partial_cmp", + [] + |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. +End Impl_core_cmp_PartialOrd_for_revm_precompile_PrecompileSpecId. + +Module Impl_revm_precompile_PrecompileSpecId. + Definition Self : Ty.t := Ty.path "revm_precompile::PrecompileSpecId". + + (* + pub const fn from_spec_id(spec_id: revm_primitives::SpecId) -> Self { + use revm_primitives::SpecId::*; + match spec_id { + FRONTIER | FRONTIER_THAWING | HOMESTEAD | DAO_FORK | TANGERINE | SPURIOUS_DRAGON => { + Self::HOMESTEAD + } + BYZANTIUM | CONSTANTINOPLE | PETERSBURG => Self::BYZANTIUM, + ISTANBUL | MUIR_GLACIER => Self::ISTANBUL, + BERLIN | LONDON | ARROW_GLACIER | GRAY_GLACIER | MERGE | SHANGHAI => Self::BERLIN, + CANCUN | PRAGUE => Self::CANCUN, + LATEST => Self::LATEST, + #[cfg(feature = "optimism")] + BEDROCK | REGOLITH | CANYON => Self::BERLIN, + #[cfg(feature = "optimism")] + ECOTONE => Self::CANCUN, + } + } + *) + Definition from_spec_id (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + M.read (| + M.match_operator (| + spec_id, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::FRONTIER" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::FRONTIER_THAWING" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::HOMESTEAD" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::DAO_FORK" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::TANGERINE" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple "revm_precompile::PrecompileSpecId::HOMESTEAD" [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::BYZANTIUM" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::CONSTANTINOPLE" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::PETERSBURG" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple "revm_precompile::PrecompileSpecId::BYZANTIUM" [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::ISTANBUL" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::MUIR_GLACIER" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple "revm_precompile::PrecompileSpecId::ISTANBUL" [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::BERLIN" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::LONDON" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::ARROW_GLACIER" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::GRAY_GLACIER" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::MERGE" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::SHANGHAI" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple "revm_precompile::PrecompileSpecId::BERLIN" [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::CANCUN" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::PRAGUE" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple "revm_precompile::PrecompileSpecId::CANCUN" [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::LATEST" |) in + M.alloc (| Value.StructTuple "revm_precompile::PrecompileSpecId::LATEST" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_from_spec_id : M.IsAssociatedFunction Self "from_spec_id" from_spec_id. +End Impl_revm_precompile_PrecompileSpecId. + +(* +pub const fn u64_to_address(x: u64) -> Address { + let x = x.to_be_bytes(); + Address::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], + ]) +} +*) +Definition u64_to_address (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ x ] => + ltac:(M.monadic + (let x := M.alloc (| x |) in + M.read (| + let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "to_be_bytes", [] |), + [ M.read (| x |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "new", + [] + |), + [ + Value.Array + [ + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + M.read (| M.SubPointer.get_array_field (| x, M.alloc (| Value.Integer 0 |) |) |); + M.read (| M.SubPointer.get_array_field (| x, M.alloc (| Value.Integer 1 |) |) |); + M.read (| M.SubPointer.get_array_field (| x, M.alloc (| Value.Integer 2 |) |) |); + M.read (| M.SubPointer.get_array_field (| x, M.alloc (| Value.Integer 3 |) |) |); + M.read (| M.SubPointer.get_array_field (| x, M.alloc (| Value.Integer 4 |) |) |); + M.read (| M.SubPointer.get_array_field (| x, M.alloc (| Value.Integer 5 |) |) |); + M.read (| M.SubPointer.get_array_field (| x, M.alloc (| Value.Integer 6 |) |) |); + M.read (| M.SubPointer.get_array_field (| x, M.alloc (| Value.Integer 7 |) |) |) + ] + ] + |) + |) + |))) + | _, _ => M.impossible + end. + +Axiom Function_u64_to_address : M.IsFunction "revm_precompile::u64_to_address" u64_to_address. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/modexp.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/modexp.md new file mode 100644 index 00000000..76cf88e5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/modexp.md @@ -0,0 +1,1786 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/precompile/modexp.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module modexp. + Definition value_BYZANTIUM : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 5 ] + |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_precompile::modexp::byzantium_run", [] |)) + ] + ] + |))). + + Definition value_BERLIN : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 5 ] + |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_precompile::modexp::berlin_run", [] |)) + ] + ] + |))). + + (* + pub fn byzantium_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + run_inner(input, gas_limit, 0, |a, b, c, d| { + byzantium_gas_calc(a, b, c, d) + }) + } + *) + Definition byzantium_run (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_limit := M.alloc (| gas_limit |) in + M.call_closure (| + M.get_function (| + "revm_precompile::modexp::run_inner", + [ + Ty.function + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path "u64"; + Ty.path "u64"; + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ] + ] + ] + (Ty.path "u64") + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| gas_limit |); + Value.Integer 0; + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1; ฮฑ2; ฮฑ3 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let b := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ2 |), + [ + fun ฮณ => + ltac:(M.monadic + (let c := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ3 |), + [ + fun ฮณ => + ltac:(M.monadic + (let d := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm_precompile::modexp::byzantium_gas_calc", + [] + |), + [ + M.read (| a |); + M.read (| b |); + M.read (| c |); + M.read (| d |) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_byzantium_run : + M.IsFunction "revm_precompile::modexp::byzantium_run" byzantium_run. + + (* + pub fn berlin_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + run_inner(input, gas_limit, 200, |a, b, c, d| { + berlin_gas_calc(a, b, c, d) + }) + } + *) + Definition berlin_run (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_limit := M.alloc (| gas_limit |) in + M.call_closure (| + M.get_function (| + "revm_precompile::modexp::run_inner", + [ + Ty.function + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path "u64"; + Ty.path "u64"; + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ] + ] + ] + (Ty.path "u64") + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| gas_limit |); + Value.Integer 200; + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1; ฮฑ2; ฮฑ3 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let b := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ2 |), + [ + fun ฮณ => + ltac:(M.monadic + (let c := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ3 |), + [ + fun ฮณ => + ltac:(M.monadic + (let d := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm_precompile::modexp::berlin_gas_calc", + [] + |), + [ + M.read (| a |); + M.read (| b |); + M.read (| c |); + M.read (| d |) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_berlin_run : M.IsFunction "revm_precompile::modexp::berlin_run" berlin_run. + + (* + pub fn calculate_iteration_count(exp_length: u64, exp_highp: &U256) -> u64 { + let mut iteration_count: u64 = 0; + + if exp_length <= 32 && *exp_highp == U256::ZERO { + iteration_count = 0; + } else if exp_length <= 32 { + iteration_count = exp_highp.bit_len() as u64 - 1; + } else if exp_length > 32 { + iteration_count = (8u64.saturating_mul(exp_length - 32)) + .saturating_add(max(1, exp_highp.bit_len() as u64) - 1); + } + + max(iteration_count, 1) + } + *) + Definition calculate_iteration_count (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ exp_length; exp_highp ] => + ltac:(M.monadic + (let exp_length := M.alloc (| exp_length |) in + let exp_highp := M.alloc (| exp_highp |) in + M.read (| + let~ iteration_count := M.alloc (| Value.Integer 0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + BinOp.Pure.le (M.read (| exp_length |)) (Value.Integer 32), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| exp_highp |); M.get_constant (| "ruint::ZERO" |) ] + |))) + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := M.write (| iteration_count, Value.Integer 0 |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.le (M.read (| exp_length |)) (Value.Integer 32) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.write (| + iteration_count, + BinOp.Wrap.sub + Integer.U64 + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "bit_len", + [] + |), + [ M.read (| exp_highp |) ] + |))) + (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt (M.read (| exp_length |)) (Value.Integer 32) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + iteration_count, + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "saturating_add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "saturating_mul", + [] + |), + [ + Value.Integer 8; + BinOp.Wrap.sub + Integer.U64 + (M.read (| exp_length |)) + (Value.Integer 32) + ] + |); + BinOp.Wrap.sub + Integer.U64 + (M.call_closure (| + M.get_function (| + "core::cmp::max", + [ Ty.path "u64" ] + |), + [ + Value.Integer 1; + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "bit_len", + [] + |), + [ M.read (| exp_highp |) ] + |)) + ] + |)) + (Value.Integer 1) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_function (| "core::cmp::max", [ Ty.path "u64" ] |), + [ M.read (| iteration_count |); Value.Integer 1 ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_calculate_iteration_count : + M.IsFunction "revm_precompile::modexp::calculate_iteration_count" calculate_iteration_count. + + (* + pub fn run_inner(input: &[u8], gas_limit: u64, min_gas: u64, calc_gas: F) -> PrecompileResult + where + F: FnOnce(u64, u64, u64, &U256) -> u64, + { + // If there is no minimum gas, return error. + if min_gas > gas_limit { + return Err(Error::OutOfGas); + } + + // The format of input is: + // + // Where every length is a 32-byte left-padded integer representing the number of bytes + // to be taken up by the next value + const HEADER_LENGTH: usize = 96; + + // Extract the header. + let base_len = U256::from_be_bytes(right_pad_with_offset::<32>(input, 0).into_owned()); + let exp_len = U256::from_be_bytes(right_pad_with_offset::<32>(input, 32).into_owned()); + let mod_len = U256::from_be_bytes(right_pad_with_offset::<32>(input, 64).into_owned()); + + // cast base and modulus to usize, it does not make sense to handle larger values + let Ok(base_len) = usize::try_from(base_len) else { + return Err(Error::ModexpBaseOverflow); + }; + let Ok(mod_len) = usize::try_from(mod_len) else { + return Err(Error::ModexpModOverflow); + }; + + // Handle a special case when both the base and mod length are zero. + if base_len == 0 && mod_len == 0 { + return Ok((min_gas, Bytes::new())); + } + + // Cast exponent length to usize, since it does not make sense to handle larger values. + let Ok(exp_len) = usize::try_from(exp_len) else { + return Err(Error::ModexpModOverflow); + }; + + // Used to extract ADJUSTED_EXPONENT_LENGTH. + let exp_highp_len = min(exp_len, 32); + + // Throw away the header data as we already extracted lengths. + let input = input.get(HEADER_LENGTH..).unwrap_or_default(); + + let exp_highp = { + // get right padded bytes so if data.len is less then exp_len we will get right padded zeroes. + let right_padded_highp = right_pad_with_offset::<32>(input, base_len); + // If exp_len is less then 32 bytes get only exp_len bytes and do left padding. + let out = left_pad::<32>(&right_padded_highp[..exp_highp_len]); + U256::from_be_bytes(out.into_owned()) + }; + + // Check if we have enough gas. + let gas_cost = calc_gas(base_len as u64, exp_len as u64, mod_len as u64, &exp_highp); + if gas_cost > gas_limit { + return Err(Error::OutOfGas); + } + + // Padding is needed if the input does not contain all 3 values. + let input_len = base_len.saturating_add(exp_len).saturating_add(mod_len); + let input = right_pad_vec(input, input_len); + let (base, input) = input.split_at(base_len); + let (exponent, modulus) = input.split_at(exp_len); + debug_assert_eq!(modulus.len(), mod_len); + + // Call the modexp. + let output = modexp(base, exponent, modulus); + + // left pad the result to modulus length. bytes will always by less or equal to modulus length. + Ok((gas_cost, left_pad_vec(&output, mod_len).into_owned().into())) + } + *) + Definition run_inner (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ F ], [ input; gas_limit; min_gas; calc_gas ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_limit := M.alloc (| gas_limit |) in + let min_gas := M.alloc (| min_gas |) in + let calc_gas := M.alloc (| calc_gas |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt (M.read (| min_gas |)) (M.read (| gas_limit |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ base_len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from_be_bytes", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + "into_owned", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_precompile::utilities::right_pad_with_offset", + [] + |), + [ M.read (| input |); Value.Integer 0 ] + |) + ] + |) + ] + |) + |) in + let~ exp_len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from_be_bytes", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + "into_owned", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_precompile::utilities::right_pad_with_offset", + [] + |), + [ M.read (| input |); Value.Integer 32 ] + |) + ] + |) + ] + |) + |) in + let~ mod_len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from_be_bytes", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + "into_owned", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_precompile::utilities::right_pad_with_offset", + [] + |), + [ M.read (| input |); Value.Integer 64 ] + |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ M.read (| base_len |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let base_len := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ M.read (| mod_len |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let mod_len := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| base_len |)) + (Value.Integer 0), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| mod_len |)) + (Value.Integer 0))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| min_gas |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |) + ] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "usize", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ M.read (| exp_len |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let exp_len := M.copy (| ฮณ0_0 |) in + let~ exp_highp_len := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::cmp::min", + [ Ty.path "usize" ] + |), + [ M.read (| exp_len |); Value.Integer 32 ] + |) + |) in + let~ input := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ + Ty.apply + (Ty.path "core::ops::range::RangeFrom") + [ Ty.path "usize" ] + ] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ + ("start", + M.read (| + M.get_constant (| + "revm_precompile::modexp::run_inner::HEADER_LENGTH" + |) + |)) + ] + ] + |) + ] + |) + |) in + let~ exp_highp := + M.copy (| + let~ right_padded_highp := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::utilities::right_pad_with_offset", + [] + |), + [ M.read (| input |); M.read (| base_len |) ] + |) + |) in + let~ out := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::utilities::left_pad", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ + Ty.apply + (Ty.path "array") + [ Ty.path "u8" ] + ], + [], + "deref", + [] + |), + [ right_padded_highp ] + |); + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", M.read (| exp_highp_len |)) ] + ] + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from_be_bytes", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] + ], + "into_owned", + [] + |), + [ M.read (| out |) ] + |) + ] + |) + |) + |) in + let~ gas_cost := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnOnce", + F, + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path "u64"; + Ty.path "u64"; + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ] + ] + ], + "call_once", + [] + |), + [ + M.read (| calc_gas |); + Value.Tuple + [ + M.rust_cast (M.read (| base_len |)); + M.rust_cast (M.read (| exp_len |)); + M.rust_cast (M.read (| mod_len |)); + exp_highp + ] + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| gas_cost |)) + (M.read (| gas_limit |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ input_len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_add", + [] + |), + [ M.read (| base_len |); M.read (| exp_len |) ] + |); + M.read (| mod_len |) + ] + |) + |) in + let~ input := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::utilities::right_pad_vec", + [] + |), + [ M.read (| input |); M.read (| input_len |) ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "split_at", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [], + "deref", + [] + |), + [ input ] + |); + M.read (| base_len |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let base := M.copy (| ฮณ0_0 |) in + let input := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "split_at", + [] + |), + [ M.read (| input |); M.read (| exp_len |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let exponent := M.copy (| ฮณ0_0 |) in + let modulus := M.copy (| ฮณ0_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + Value.Bool true + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| + Value.Tuple + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| modulus |) + ] + |) + |); + mod_len + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let left_val := + M.copy (| ฮณ0_0 |) in + let right_val := + M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (BinOp.Pure.eq + (M.read (| + M.read (| + left_val + |) + |)) + (M.read (| + M.read (| + right_val + |) + |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Bool + true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ kind := + M.alloc (| + Value.StructTuple + "core::panicking::AssertKind::Eq" + [] + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "core::panicking::assert_failed", + [ + Ty.path + "usize"; + Ty.path + "usize" + ] + |), + [ + M.read (| + kind + |); + M.read (| + left_val + |); + M.read (| + right_val + |); + Value.StructTuple + "core::option::Option::None" + [] + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ output := + M.alloc (| + M.call_closure (| + M.get_function (| + "aurora_engine_modexp::modexp", + [] + |), + [ + M.read (| base |); + M.read (| exponent |); + M.read (| modulus |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| gas_cost |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "u8"; + Ty.path + "alloc::alloc::Global" + ], + [ + Ty.path + "alloy_primitives::bytes_::Bytes" + ], + "into", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::borrow::Cow") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ], + "into_owned", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_precompile::utilities::left_pad_vec", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path "u8"; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ output ] + |); + M.read (| mod_len |) + ] + |) + ] + |) + ] + |) + ] + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_run_inner : M.IsFunction "revm_precompile::modexp::run_inner" run_inner. + + Module run_inner. + Definition value_HEADER_LENGTH : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 96 |))). + End run_inner. + + (* + pub fn byzantium_gas_calc(base_len: u64, exp_len: u64, mod_len: u64, exp_highp: &U256) -> u64 { + // output of this function is bounded by 2^128 + fn mul_complexity(x: u64) -> U256 { + if x <= 64 { + U256::from(x * x) + } else if x <= 1_024 { + U256::from(x * x / 4 + 96 * x - 3_072) + } else { + // up-cast to avoid overflow + let x = U256::from(x); + let x_sq = x * x; // x < 2^64 => x*x < 2^128 < 2^256 (no overflow) + x_sq / U256::from(16) + U256::from(480) * x - U256::from(199_680) + } + } + + let mul = mul_complexity(core::cmp::max(mod_len, base_len)); + let iter_count = U256::from(calculate_iteration_count(exp_len, exp_highp)); + // mul * iter_count bounded by 2^195 < 2^256 (no overflow) + let gas = (mul * iter_count) / U256::from(20); + gas.saturating_to() + } + *) + Definition byzantium_gas_calc (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ base_len; exp_len; mod_len; exp_highp ] => + ltac:(M.monadic + (let base_len := M.alloc (| base_len |) in + let exp_len := M.alloc (| exp_len |) in + let mod_len := M.alloc (| mod_len |) in + let exp_highp := M.alloc (| exp_highp |) in + M.read (| + let~ mul := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::modexp::byzantium_gas_calc.mul_complexity", + [] + |), + [ + M.call_closure (| + M.get_function (| "core::cmp::max", [ Ty.path "u64" ] |), + [ M.read (| mod_len |); M.read (| base_len |) ] + |) + ] + |) + |) in + let~ iter_count := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from", [ Ty.path "u64" ] |), + [ + M.call_closure (| + M.get_function (| "revm_precompile::modexp::calculate_iteration_count", [] |), + [ M.read (| exp_len |); M.read (| exp_highp |) ] + |) + ] + |) + |) in + let~ gas := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Div", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "div", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Mul", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "mul", + [] + |), + [ M.read (| mul |); M.read (| iter_count |) ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 20 ] + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "saturating_to", + [ Ty.path "u64" ] + |), + [ gas ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_byzantium_gas_calc : + M.IsFunction "revm_precompile::modexp::byzantium_gas_calc" byzantium_gas_calc. + + Module byzantium_gas_calc. + (* + fn mul_complexity(x: u64) -> U256 { + if x <= 64 { + U256::from(x * x) + } else if x <= 1_024 { + U256::from(x * x / 4 + 96 * x - 3_072) + } else { + // up-cast to avoid overflow + let x = U256::from(x); + let x_sq = x * x; // x < 2^64 => x*x < 2^128 < 2^256 (no overflow) + x_sq / U256::from(16) + U256::from(480) * x - U256::from(199_680) + } + } + *) + Definition mul_complexity (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ x ] => + ltac:(M.monadic + (let x := M.alloc (| x |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use (M.alloc (| BinOp.Pure.le (M.read (| x |)) (Value.Integer 64) |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ BinOp.Wrap.mul Integer.U64 (M.read (| x |)) (M.read (| x |)) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.le (M.read (| x |)) (Value.Integer 1024) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + BinOp.Wrap.sub + Integer.U64 + (BinOp.Wrap.add + Integer.U64 + (BinOp.Wrap.div + Integer.U64 + (BinOp.Wrap.mul + Integer.U64 + (M.read (| x |)) + (M.read (| x |))) + (Value.Integer 4)) + (BinOp.Wrap.mul + Integer.U64 + (Value.Integer 96) + (M.read (| x |)))) + (Value.Integer 3072) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let~ x := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ M.read (| x |) ] + |) + |) in + let~ x_sq := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Mul", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "mul", + [] + |), + [ M.read (| x |); M.read (| x |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Sub", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "sub", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Add", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "add", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Div", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "div", + [] + |), + [ + M.read (| x_sq |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 16 ] + |) + ] + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Mul", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "mul", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 480 ] + |); + M.read (| x |) + ] + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 199680 ] + |) + ] + |) + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_mul_complexity : + M.IsFunction "revm_precompile::modexp::byzantium_gas_calc::mul_complexity" mul_complexity. + End byzantium_gas_calc. + + (* + pub fn berlin_gas_calc( + base_length: u64, + exp_length: u64, + mod_length: u64, + exp_highp: &U256, + ) -> u64 { + fn calculate_multiplication_complexity(base_length: u64, mod_length: u64) -> U256 { + let max_length = max(base_length, mod_length); + let mut words = max_length / 8; + if max_length % 8 > 0 { + words += 1; + } + let words = U256::from(words); + words * words + } + + let multiplication_complexity = calculate_multiplication_complexity(base_length, mod_length); + let iteration_count = calculate_iteration_count(exp_length, exp_highp); + let gas = (multiplication_complexity * U256::from(iteration_count)) / U256::from(3); + max(200, gas.saturating_to()) + } + *) + Definition berlin_gas_calc (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ base_length; exp_length; mod_length; exp_highp ] => + ltac:(M.monadic + (let base_length := M.alloc (| base_length |) in + let exp_length := M.alloc (| exp_length |) in + let mod_length := M.alloc (| mod_length |) in + let exp_highp := M.alloc (| exp_highp |) in + M.read (| + let~ multiplication_complexity := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_precompile::modexp::berlin_gas_calc.calculate_multiplication_complexity", + [] + |), + [ M.read (| base_length |); M.read (| mod_length |) ] + |) + |) in + let~ iteration_count := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::modexp::calculate_iteration_count", [] |), + [ M.read (| exp_length |); M.read (| exp_highp |) ] + |) + |) in + let~ gas := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Div", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "div", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Mul", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "mul", + [] + |), + [ + M.read (| multiplication_complexity |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ M.read (| iteration_count |) ] + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 3 ] + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_function (| "core::cmp::max", [ Ty.path "u64" ] |), + [ + Value.Integer 200; + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "saturating_to", + [ Ty.path "u64" ] + |), + [ gas ] + |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_berlin_gas_calc : + M.IsFunction "revm_precompile::modexp::berlin_gas_calc" berlin_gas_calc. + + Module berlin_gas_calc. + (* + fn calculate_multiplication_complexity(base_length: u64, mod_length: u64) -> U256 { + let max_length = max(base_length, mod_length); + let mut words = max_length / 8; + if max_length % 8 > 0 { + words += 1; + } + let words = U256::from(words); + words * words + } + *) + Definition calculate_multiplication_complexity (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ base_length; mod_length ] => + ltac:(M.monadic + (let base_length := M.alloc (| base_length |) in + let mod_length := M.alloc (| mod_length |) in + M.read (| + let~ max_length := + M.alloc (| + M.call_closure (| + M.get_function (| "core::cmp::max", [ Ty.path "u64" ] |), + [ M.read (| base_length |); M.read (| mod_length |) ] + |) + |) in + let~ words := + M.alloc (| + BinOp.Wrap.div Integer.U64 (M.read (| max_length |)) (Value.Integer 8) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (BinOp.Wrap.rem + Integer.U64 + (M.read (| max_length |)) + (Value.Integer 8)) + (Value.Integer 0) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + let ฮฒ := words in + M.write (| + ฮฒ, + BinOp.Wrap.add Integer.U64 (M.read (| ฮฒ |)) (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ words := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from", [ Ty.path "u64" ] |), + [ M.read (| words |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Mul", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "mul", + [] + |), + [ M.read (| words |); M.read (| words |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_calculate_multiplication_complexity : + M.IsFunction + "revm_precompile::modexp::berlin_gas_calc::calculate_multiplication_complexity" + calculate_multiplication_complexity. + End berlin_gas_calc. +End modexp. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/secp256k1.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/secp256k1.md new file mode 100644 index 00000000..357801e3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/secp256k1.md @@ -0,0 +1,898 @@ +# ๐Ÿ“ secp256k1.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/precompile/secp256k1.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module secp256k1. + Definition value_ECRECOVER : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_precompile::PrecompileWithAddress" + [ + M.call_closure (| + M.get_function (| "revm_precompile::u64_to_address", [] |), + [ Value.Integer 1 ] + |); + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + (* ReifyFnPointer *) + M.pointer_coercion + (M.get_function (| "revm_precompile::secp256k1::ec_recover_run", [] |)) + ] + ] + |))). + + Module secp256k1. + (* + pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { + let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); + let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; + + let secp = Secp256k1::new(); + let msg = Message::from_digest(msg.0); + let public = secp.recover_ecdsa(&msg, &sig)?; + + let mut hash = keccak256(&public.serialize_uncompressed()[1..]); + hash[..12].fill(0); + Ok(hash) + } + *) + Definition ecrecover (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ sig; recid; msg ] => + ltac:(M.monadic + (let sig := M.alloc (| sig |) in + let recid := M.alloc (| recid |) in + let msg := M.alloc (| msg |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ recid := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "secp256k1::ecdsa::recovery::RecoveryId"; + Ty.path "secp256k1::Error" + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "secp256k1::ecdsa::recovery::RecoveryId", + "from_i32", + [] + |), + [ M.rust_cast (M.read (| recid |)) ] + |); + M.read (| Value.String "recovery ID is valid" |) + ] + |) + |) in + let~ sig := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "secp256k1::ecdsa::recovery::RecoverableSignature"; + Ty.path "secp256k1::Error" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "secp256k1::ecdsa::recovery::RecoverableSignature", + "from_compact", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + "as_slice", + [] + |), + [ M.read (| sig |) ] + |); + M.read (| recid |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "secp256k1::Error" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "secp256k1::Error" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ secp := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "secp256k1::Secp256k1") + [ Ty.path "secp256k1::context::alloc_only::All" ], + "new", + [] + |), + [] + |) + |) in + let~ msg := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "secp256k1::Message", + "from_digest", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_tuple_field (| + M.read (| msg |), + "alloy_primitives::bits::fixed::FixedBytes", + 0 + |) + |) + ] + |) + |) in + let~ public := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "secp256k1::key::PublicKey"; Ty.path "secp256k1::Error" ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "secp256k1::Secp256k1") + [ Ty.path "secp256k1::context::alloc_only::All" ], + "recover_ecdsa", + [] + |), + [ secp; msg; sig ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "secp256k1::Error" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "secp256k1::Error" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ hash := + M.alloc (| + M.call_closure (| + M.get_function (| + "alloy_primitives::utils::keccak256", + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::RangeFrom") [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "secp256k1::key::PublicKey", + "serialize_uncompressed", + [] + |), + [ public ] + |) + |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", Value.Integer 1) ] + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "fill", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ], + "index_mut", + [] + |), + [ + hash; + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", Value.Integer 12) ] + ] + |); + Value.Integer 0 + ] + |) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ M.read (| hash |) ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_ecrecover : + M.IsFunction "revm_precompile::secp256k1::secp256k1::ecrecover" ecrecover. + End secp256k1. + + (* + pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + const ECRECOVER_BASE: u64 = 3_000; + + if ECRECOVER_BASE > gas_limit { + return Err(Error::OutOfGas); + } + + let input = right_pad::<128>(input); + + // `v` must be a 32-byte big-endian integer equal to 27 or 28. + if !(input[32..63].iter().all(|&b| b == 0) && matches!(input[63], 27 | 28)) { + return Ok((ECRECOVER_BASE, Bytes::new())); + } + + let msg = <&B256>::try_from(&input[0..32]).unwrap(); + let recid = input[63] - 27; + let sig = <&B512>::try_from(&input[64..128]).unwrap(); + + let out = secp256k1::ecrecover(sig, recid, msg) + .map(|o| o.to_vec().into()) + .unwrap_or_default(); + Ok((ECRECOVER_BASE, out)) + } + *) + Definition ec_recover_run (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; gas_limit ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let gas_limit := M.alloc (| gas_limit |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| + M.get_constant (| + "revm_precompile::secp256k1::ec_recover_run::ECRECOVER_BASE" + |) + |)) + (M.read (| gas_limit |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ input := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_precompile::utilities::right_pad", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply (Ty.path "core::slice::iter::Iter") [ Ty.path "u8" ], + [], + "all", + [ + Ty.function + [ Ty.tuple [ Ty.apply (Ty.path "&") [ Ty.path "u8" ] ] ] + (Ty.path "bool") + ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] + ], + [], + "deref", + [] + |), + [ input ] + |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 32); + ("end_", Value.Integer 63) + ] + ] + |) + ] + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let b := M.copy (| ฮณ |) in + BinOp.Pure.eq + (M.read (| b |)) + (Value.Integer 0))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.SubPointer.get_array_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "deref", + [] + |), + [ input ] + |), + M.alloc (| Value.Integer 63 |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 27 + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Integer 28 + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| + M.get_constant (| + "revm_precompile::secp256k1::ec_recover_run::ECRECOVER_BASE" + |) + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |) + ] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ msg := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ], + "try_from", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "deref", + [] + |), + [ input ] + |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 0); ("end_", Value.Integer 32) ] + ] + |) + ] + |) + ] + |) + |) in + let~ recid := + M.alloc (| + BinOp.Wrap.sub + Integer.U8 + (M.read (| + M.SubPointer.get_array_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "deref", + [] + |), + [ input ] + |), + M.alloc (| Value.Integer 63 |) + |) + |)) + (Value.Integer 27) + |) in + let~ sig := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ], + "try_from", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::borrow::Cow") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "deref", + [] + |), + [ input ] + |); + Value.StructRecord + "core::ops::range::Range" + [ ("start", Value.Integer 64); ("end_", Value.Integer 128) ] + ] + |) + ] + |) + ] + |) + |) in + let~ out := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "secp256k1::Error" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "secp256k1::Error" + ], + "map", + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.function + [ Ty.tuple [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ] ] + (Ty.path "alloy_primitives::bytes_::Bytes") + ] + |), + [ + M.call_closure (| + M.get_function (| + "revm_precompile::secp256k1::secp256k1::ecrecover", + [] + |), + [ M.read (| sig |); M.read (| recid |); M.read (| msg |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let o := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "to_vec", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path + "alloy_primitives::bits::fixed::FixedBytes", + [], + "deref", + [] + |), + [ o ] + |)) + ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| + M.get_constant (| + "revm_precompile::secp256k1::ec_recover_run::ECRECOVER_BASE" + |) + |); + M.read (| out |) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_ec_recover_run : + M.IsFunction "revm_precompile::secp256k1::ec_recover_run" ec_recover_run. + + Module ec_recover_run. + Definition value_ECRECOVER_BASE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 3000 |))). + End ec_recover_run. +End secp256k1. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/utilities.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/utilities.md new file mode 100644 index 00000000..095d743e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/precompile/utilities.md @@ -0,0 +1,716 @@ +# ๐Ÿ“ utilities.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/precompile/utilities.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module utilities. + (* + pub fn right_pad_with_offset(data: &[u8], offset: usize) -> Cow<'_, [u8; LEN]> { + right_pad(data.get(offset..).unwrap_or_default()) + } + *) + Definition right_pad_with_offset (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ data; offset ] => + ltac:(M.monadic + (let data := M.alloc (| data |) in + let offset := M.alloc (| offset |) in + M.call_closure (| + M.get_function (| "revm_precompile::utilities::right_pad", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ Ty.apply (Ty.path "core::ops::range::RangeFrom") [ Ty.path "usize" ] ] + |), + [ + M.read (| data |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", M.read (| offset |)) ] + ] + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_right_pad_with_offset : + M.IsFunction "revm_precompile::utilities::right_pad_with_offset" right_pad_with_offset. + + (* + pub fn right_pad_with_offset_vec(data: &[u8], offset: usize, len: usize) -> Cow<'_, [u8]> { + right_pad_vec(data.get(offset..).unwrap_or_default(), len) + } + *) + Definition right_pad_with_offset_vec (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ data; offset; len ] => + ltac:(M.monadic + (let data := M.alloc (| data |) in + let offset := M.alloc (| offset |) in + let len := M.alloc (| len |) in + M.call_closure (| + M.get_function (| "revm_precompile::utilities::right_pad_vec", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ Ty.apply (Ty.path "core::ops::range::RangeFrom") [ Ty.path "usize" ] ] + |), + [ + M.read (| data |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", M.read (| offset |)) ] + ] + |) + ] + |); + M.read (| len |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_right_pad_with_offset_vec : + M.IsFunction "revm_precompile::utilities::right_pad_with_offset_vec" right_pad_with_offset_vec. + + (* + pub fn right_pad(data: &[u8]) -> Cow<'_, [u8; LEN]> { + if let Some(data) = data.get(..LEN) { + Cow::Borrowed(data.try_into().unwrap()) + } else { + let mut padded = [0; LEN]; + padded[..data.len()].copy_from_slice(data); + Cow::Owned(padded) + } + } + *) + Definition right_pad (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ data ] => + ltac:(M.monadic + (let data := M.alloc (| data |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ] + |), + [ + M.read (| data |); + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.read (| + M.get_constant (| "revm_precompile::utilities::right_pad::LEN" |) + |)) + ] + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| ฮณ, "core::option::Option::Some", 0 |) in + let data := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "alloc::borrow::Cow::Borrowed" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] + ], + "try_into", + [] + |), + [ M.read (| data |) ] + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ padded := M.alloc (| repeat (Value.Integer 0) LEN |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + padded; + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| data |) ] + |)) + ] + ] + |); + M.read (| data |) + ] + |) + |) in + M.alloc (| + Value.StructTuple "alloc::borrow::Cow::Owned" [ M.read (| padded |) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_right_pad : M.IsFunction "revm_precompile::utilities::right_pad" right_pad. + + (* + pub fn right_pad_vec(data: &[u8], len: usize) -> Cow<'_, [u8]> { + if let Some(data) = data.get(..len) { + Cow::Borrowed(data) + } else { + let mut padded = vec![0; len]; + padded[..data.len()].copy_from_slice(data); + Cow::Owned(padded) + } + } + *) + Definition right_pad_vec (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ data; len ] => + ltac:(M.monadic + (let data := M.alloc (| data |) in + let len := M.alloc (| len |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ] + |), + [ + M.read (| data |); + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", M.read (| len |)) ] + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| ฮณ, "core::option::Option::Some", 0 |) in + let data := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple "alloc::borrow::Cow::Borrowed" [ M.read (| data |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ padded := + M.alloc (| + M.call_closure (| + M.get_function (| "alloc::vec::from_elem", [ Ty.path "u8" ] |), + [ Value.Integer 0; M.read (| len |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + padded; + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| data |) ] + |)) + ] + ] + |); + M.read (| data |) + ] + |) + |) in + M.alloc (| + Value.StructTuple "alloc::borrow::Cow::Owned" [ M.read (| padded |) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_right_pad_vec : + M.IsFunction "revm_precompile::utilities::right_pad_vec" right_pad_vec. + + (* + pub fn left_pad(data: &[u8]) -> Cow<'_, [u8; LEN]> { + if let Some(data) = data.get(..LEN) { + Cow::Borrowed(data.try_into().unwrap()) + } else { + let mut padded = [0; LEN]; + padded[LEN - data.len()..].copy_from_slice(data); + Cow::Owned(padded) + } + } + *) + Definition left_pad (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ data ] => + ltac:(M.monadic + (let data := M.alloc (| data |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ] + |), + [ + M.read (| data |); + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.read (| + M.get_constant (| "revm_precompile::utilities::left_pad::LEN" |) + |)) + ] + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| ฮณ, "core::option::Option::Some", 0 |) in + let data := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "alloc::borrow::Cow::Borrowed" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ]; + Ty.path "core::array::TryFromSliceError" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ], + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] + ], + "try_into", + [] + |), + [ M.read (| data |) ] + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ padded := M.alloc (| repeat (Value.Integer 0) LEN |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::RangeFrom") [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + padded; + Value.StructRecord + "core::ops::range::RangeFrom" + [ + ("start", + BinOp.Wrap.sub + Integer.Usize + (M.read (| + M.get_constant (| + "revm_precompile::utilities::left_pad::LEN" + |) + |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| data |) ] + |))) + ] + ] + |); + M.read (| data |) + ] + |) + |) in + M.alloc (| + Value.StructTuple "alloc::borrow::Cow::Owned" [ M.read (| padded |) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_left_pad : M.IsFunction "revm_precompile::utilities::left_pad" left_pad. + + (* + pub fn left_pad_vec(data: &[u8], len: usize) -> Cow<'_, [u8]> { + if let Some(data) = data.get(..len) { + Cow::Borrowed(data) + } else { + let mut padded = vec![0; len]; + padded[len - data.len()..].copy_from_slice(data); + Cow::Owned(padded) + } + } + *) + Definition left_pad_vec (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ data; len ] => + ltac:(M.monadic + (let data := M.alloc (| data |) in + let len := M.alloc (| len |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ] + |), + [ + M.read (| data |); + Value.StructRecord + "core::ops::range::RangeTo" + [ ("end_", M.read (| len |)) ] + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| ฮณ, "core::option::Option::Some", 0 |) in + let data := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple "alloc::borrow::Cow::Borrowed" [ M.read (| data |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ padded := + M.alloc (| + M.call_closure (| + M.get_function (| "alloc::vec::from_elem", [ Ty.path "u8" ] |), + [ Value.Integer 0; M.read (| len |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "copy_from_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::IndexMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ Ty.apply (Ty.path "core::ops::range::RangeFrom") [ Ty.path "usize" ] + ], + "index_mut", + [] + |), + [ + padded; + Value.StructRecord + "core::ops::range::RangeFrom" + [ + ("start", + BinOp.Wrap.sub + Integer.Usize + (M.read (| len |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| data |) ] + |))) + ] + ] + |); + M.read (| data |) + ] + |) + |) in + M.alloc (| + Value.StructTuple "alloc::borrow::Cow::Owned" [ M.read (| padded |) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_left_pad_vec : + M.IsFunction "revm_precompile::utilities::left_pad_vec" left_pad_vec. + + (* + pub const fn bool_to_bytes32(value: bool) -> Bytes { + Bytes::from_static(&bool_to_b256(value).0) + } + *) + Definition bool_to_bytes32 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "from_static", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_tuple_field (| + M.call_closure (| + M.get_function (| "revm_precompile::utilities::bool_to_b256", [] |), + [ M.read (| value |) ] + |), + "alloy_primitives::bits::fixed::FixedBytes", + 0 + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_bool_to_bytes32 : + M.IsFunction "revm_precompile::utilities::bool_to_bytes32" bool_to_bytes32. + + (* + pub const fn bool_to_b256(value: bool) -> &'static B256 { + const TRUE: &B256 = &b256!("0000000000000000000000000000000000000000000000000000000000000001"); + const FALSE: &B256 = &b256!("0000000000000000000000000000000000000000000000000000000000000000"); + if value { + TRUE + } else { + FALSE + } + } + *) + Definition bool_to_b256 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use value in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.get_constant (| "revm_precompile::utilities::bool_to_b256::TRUE" |))); + fun ฮณ => + ltac:(M.monadic + (M.get_constant (| "revm_precompile::utilities::bool_to_b256::FALSE" |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_bool_to_b256 : + M.IsFunction "revm_precompile::utilities::bool_to_b256" bool_to_b256. + + Module bool_to_b256. + Definition value_TRUE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + "new", + [] + |), + [ + M.read (| + M.get_constant (| "revm_precompile::utilities::bool_to_b256::TRUE::RES" |) + |) + ] + |) + |) + |))). + + Definition value_FALSE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + "new", + [] + |), + [ + M.read (| + M.get_constant (| "revm_precompile::utilities::bool_to_b256::FALSE::RES" |) + |) + ] + |) + |) + |))). + End bool_to_b256. +End utilities. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode.md new file mode 100644 index 00000000..8bb355f5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode.md @@ -0,0 +1,1363 @@ +# ๐Ÿ“ bytecode.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/bytecode.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module bytecode. + (* + Enum Bytecode + { + ty_params := []; + variants := + [ + { + name := "LegacyRaw"; + item := StructTuple [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + discriminant := None; + }; + { + name := "LegacyAnalyzed"; + item := + StructTuple [ Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode" ]; + discriminant := None; + }; + { + name := "Eof"; + item := StructTuple [ Ty.path "revm_primitives::bytecode::eof::Eof" ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_primitives_bytecode_Bytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::Bytecode". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::bytecode::Bytecode::LegacyRaw" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::bytecode::Bytecode::Eof" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::eof::Eof", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_bytecode_Bytecode. + + Module Impl_core_fmt_Debug_for_revm_primitives_bytecode_Bytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::Bytecode". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "LegacyRaw" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "LegacyAnalyzed" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Eof" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_bytecode_Bytecode. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_Bytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::Bytecode". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_Bytecode. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_Bytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::Bytecode". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::Bytecode" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::Bytecode" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + [ + Ty.path + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode" + ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::bytecode::eof::Eof", + [ Ty.path "revm_primitives::bytecode::eof::Eof" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::intrinsics::unreachable", [] |), + [] + |) + |) + |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_Bytecode. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_Bytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::Bytecode". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_Bytecode. + + Module Impl_core_cmp_Eq_for_revm_primitives_bytecode_Bytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::Bytecode". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_bytecode_Bytecode. + + Module Impl_core_hash_Hash_for_revm_primitives_bytecode_Bytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::Bytecode". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::Bytecode" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::bytecode::eof::Eof", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_bytecode_Bytecode. + + Module Impl_core_default_Default_for_revm_primitives_bytecode_Bytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::Bytecode". + + (* + fn default() -> Self { + // Creates a new legacy analyzed [`Bytecode`] with exactly one STOP opcode. + Self::new() + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "new", + [] + |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_bytecode_Bytecode. + + Module Impl_revm_primitives_bytecode_Bytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::Bytecode". + + (* + pub fn new() -> Self { + Self::LegacyAnalyzed(LegacyAnalyzedBytecode::default()) + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn legacy_jump_table(&self) -> Option<&JumpTable> { + match &self { + Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()), + _ => None, + } + } + *) + Definition legacy_jump_table (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.alloc (| self |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ := M.read (| ฮณ |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let analyzed := M.alloc (| ฮณ2_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "jump_table", + [] + |), + [ M.read (| analyzed |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_legacy_jump_table : + M.IsAssociatedFunction Self "legacy_jump_table" legacy_jump_table. + + (* + pub fn hash_slow(&self) -> B256 { + if self.is_empty() { + KECCAK_EMPTY + } else { + keccak256(self.original_byte_slice()) + } + } + *) + Definition hash_slow (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "is_empty", + [] + |), + [ M.read (| self |) ] + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.get_constant (| "revm_primitives::utilities::KECCAK_EMPTY" |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_function (| + "alloy_primitives::utils::keccak256", + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "original_byte_slice", + [] + |), + [ M.read (| self |) ] + |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_hash_slow : M.IsAssociatedFunction Self "hash_slow" hash_slow. + + (* + pub const fn eof(&self) -> Option<&Eof> { + match self { + Self::Eof(eof) => Some(eof), + _ => None, + } + } + *) + Definition eof (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let eof := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| eof |) ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_eof : M.IsAssociatedFunction Self "eof" eof. + + (* + pub const fn is_eof(&self) -> bool { + matches!(self, Self::Eof(_)) + } + *) + Definition is_eof (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_eof : M.IsAssociatedFunction Self "is_eof" is_eof. + + (* + pub fn new_raw(bytecode: Bytes) -> Self { + Self::LegacyRaw(bytecode) + } + *) + Definition new_raw (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ bytecode ] => + ltac:(M.monadic + (let bytecode := M.alloc (| bytecode |) in + Value.StructTuple + "revm_primitives::bytecode::Bytecode::LegacyRaw" + [ M.read (| bytecode |) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_raw : M.IsAssociatedFunction Self "new_raw" new_raw. + + (* + pub unsafe fn new_analyzed( + bytecode: Bytes, + original_len: usize, + jump_table: JumpTable, + ) -> Self { + Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new( + bytecode, + original_len, + jump_table, + )) + } + *) + Definition new_analyzed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ bytecode; original_len; jump_table ] => + ltac:(M.monadic + (let bytecode := M.alloc (| bytecode |) in + let original_len := M.alloc (| original_len |) in + let jump_table := M.alloc (| jump_table |) in + Value.StructTuple + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "new", + [] + |), + [ M.read (| bytecode |); M.read (| original_len |); M.read (| jump_table |) ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_analyzed : M.IsAssociatedFunction Self "new_analyzed" new_analyzed. + + (* + pub fn bytecode(&self) -> &Bytes { + match self { + Self::LegacyRaw(bytes) => bytes, + Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(), + Self::Eof(eof) => eof + .body + .code(0) + .expect("Valid EOF has at least one code section"), + } + } + *) + Definition bytecode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let bytes := M.alloc (| ฮณ1_0 |) in + M.alloc (| M.read (| bytes |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let analyzed := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "bytecode", + [] + |), + [ M.read (| analyzed |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let eof := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + "code", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| eof |), + "revm_primitives::bytecode::eof::Eof", + "body" + |); + Value.Integer 0 + ] + |); + M.read (| Value.String "Valid EOF has at least one code section" |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_bytecode : M.IsAssociatedFunction Self "bytecode" bytecode. + + (* + pub fn is_execution_ready(&self) -> bool { + !matches!(self, Self::LegacyRaw(_)) + } + *) + Definition is_execution_ready (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + UnOp.Pure.not + (M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_execution_ready : + M.IsAssociatedFunction Self "is_execution_ready" is_execution_ready. + + (* + pub fn original_bytes(&self) -> Bytes { + match self { + Self::LegacyRaw(bytes) => bytes.clone(), + Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(), + Self::Eof(eof) => eof.raw().clone(), + } + } + *) + Definition original_bytes (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let bytes := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ M.read (| bytes |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let analyzed := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_bytes", + [] + |), + [ M.read (| analyzed |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let eof := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "raw", + [] + |), + [ M.read (| eof |) ] + |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_original_bytes : + M.IsAssociatedFunction Self "original_bytes" original_bytes. + + (* + pub fn original_byte_slice(&self) -> &[u8] { + match self { + Self::LegacyRaw(bytes) => bytes, + Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(), + Self::Eof(eof) => eof.raw(), + } + } + *) + Definition original_byte_slice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let bytes := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| bytes |) ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let analyzed := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_byte_slice", + [] + |), + [ M.read (| analyzed |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let eof := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "raw", + [] + |), + [ M.read (| eof |) ] + |) + ] + |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_original_byte_slice : + M.IsAssociatedFunction Self "original_byte_slice" original_byte_slice. + + (* + pub fn len(&self) -> usize { + match self { + Self::LegacyRaw(bytes) => bytes.len(), + Self::LegacyAnalyzed(analyzed) => analyzed.original_len(), + Self::Eof(eof) => eof.size(), + } + } + *) + Definition len (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyRaw", + 0 + |) in + let bytes := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "bytes::bytes::Bytes", "len", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| bytes |) ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::LegacyAnalyzed", + 0 + |) in + let analyzed := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_len", + [] + |), + [ M.read (| analyzed |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::bytecode::Bytecode::Eof", + 0 + |) in + let eof := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "size", + [] + |), + [ M.read (| eof |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_len : M.IsAssociatedFunction Self "len" len. + + (* + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + *) + Definition is_empty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "len", + [] + |), + [ M.read (| self |) ] + |)) + (Value.Integer 0))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_empty : M.IsAssociatedFunction Self "is_empty" is_empty. + End Impl_revm_primitives_bytecode_Bytecode. +End bytecode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof.md new file mode 100644 index 00000000..6d61c634 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof.md @@ -0,0 +1,1734 @@ +# ๐Ÿ“ eof.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/bytecode/eof.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module bytecode. + Module eof. + (* StructRecord + { + name := "Eof"; + ty_params := []; + fields := + [ + ("header", Ty.path "revm_primitives::bytecode::eof::header::EofHeader"); + ("body", Ty.path "revm_primitives::bytecode::eof::body::EofBody"); + ("raw", Ty.path "alloy_primitives::bytes_::Bytes") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_Eof. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::Eof". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::bytecode::eof::Eof" + [ + ("header", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "header" + |) + ] + |)); + ("body", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "body" + |) + ] + |)); + ("raw", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "raw" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_Eof. + + Module Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_Eof. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::Eof". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Eof" |); + M.read (| Value.String "header" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "header" + |)); + M.read (| Value.String "body" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "body" + |)); + M.read (| Value.String "raw" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "raw" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_Eof. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_Eof. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::Eof". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_Eof. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_Eof. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::Eof". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + [ Ty.path "revm_primitives::bytecode::eof::header::EofHeader" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "header" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::Eof", + "header" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + [ Ty.path "revm_primitives::bytecode::eof::body::EofBody" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "body" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::Eof", + "body" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "raw" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::Eof", + "raw" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_Eof. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_Eof. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::Eof". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_Eof. + + Module Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_Eof. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::Eof". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_Eof. + + Module Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_Eof. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::Eof". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "header" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "body" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "raw" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_Eof. + + Module Impl_core_default_Default_for_revm_primitives_bytecode_eof_Eof. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::Eof". + + (* + fn default() -> Self { + let body = EofBody { + // types section with zero inputs, zero outputs and zero max stack size. + types_section: vec![TypesSection::default()], + // One code section with a STOP byte. + code_section: vec![[0x00].into()], + container_section: vec![], + data_section: Bytes::new(), + is_data_filled: true, + }; + body.into_eof() + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.read (| + let~ body := + M.alloc (| + Value.StructRecord + "revm_primitives::bytecode::eof::body::EofBody" + [ + ("types_section", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection" + ], + "into_vec", + [ Ty.path "alloc::alloc::Global" ] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.apply + (Ty.path "array") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection" + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection", + [], + "default", + [] + |), + [] + |) + ] + |) + ] + |) + |)) + ] + |)); + ("code_section", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into_vec", + [ Ty.path "alloc::alloc::Global" ] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.apply + (Ty.path "array") + [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply (Ty.path "array") [ Ty.path "u8" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ Value.Array [ Value.Integer 0 ] ] + |) + ] + |) + ] + |) + |)) + ] + |)); + ("container_section", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |)); + ("data_section", + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |)); + ("is_data_filled", Value.Bool true) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + "into_eof", + [] + |), + [ M.read (| body |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_bytecode_eof_Eof. + + Module Impl_revm_primitives_bytecode_eof_Eof. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::Eof". + + (* + pub fn size(&self) -> usize { + self.header.size() + self.header.body_size() + } + *) + Definition size (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.add + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + "size", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "header" + |) + ] + |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + "body_size", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "header" + |) + ] + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_size : M.IsAssociatedFunction Self "size" size. + + (* + pub fn raw(&self) -> &Bytes { + &self.raw + } + *) + Definition raw (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "raw" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_raw : M.IsAssociatedFunction Self "raw" raw. + + (* + pub fn data_slice(&self, offset: usize, len: usize) -> &[u8] { + self.body + .data_section + .get(offset..) + .and_then(|bytes| bytes.get(..min(len, bytes.len()))) + .unwrap_or(&[]) + } + *) + Definition data_slice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; offset; len ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let offset := M.alloc (| offset |) in + let len := M.alloc (| len |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] ], + "and_then", + [ + Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ] + ] + (Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ Ty.apply (Ty.path "core::ops::range::RangeFrom") [ Ty.path "usize" ] ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |) + ] + |) + ] + |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", M.read (| offset |)) ] + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let bytes := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "get", + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ] + |), + [ + M.read (| bytes |); + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.call_closure (| + M.get_function (| + "core::cmp::min", + [ Ty.path "usize" ] + |), + [ + M.read (| len |); + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| bytes |) ] + |) + ] + |)) + ] + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + (* Unsize *) M.pointer_coercion (M.alloc (| Value.Array [] |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_data_slice : M.IsAssociatedFunction Self "data_slice" data_slice. + + (* + pub fn data(&self) -> &[u8] { + &self.body.data_section + } + *) + Definition data (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "body" + |), + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_data : M.IsAssociatedFunction Self "data" data. + + (* + pub fn encode_slow(&self) -> Bytes { + let mut buffer: Vec = Vec::with_capacity(self.size()); + self.header.encode(&mut buffer); + self.body.encode(&mut buffer); + buffer.into() + } + *) + Definition encode_slow (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ buffer := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "with_capacity", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "size", + [] + |), + [ M.read (| self |) ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + "encode", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "header" + |); + buffer + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + "encode", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::Eof", + "body" + |); + buffer + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ M.read (| buffer |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_encode_slow : M.IsAssociatedFunction Self "encode_slow" encode_slow. + + (* + pub fn decode(raw: Bytes) -> Result { + let (header, _) = EofHeader::decode(&raw)?; + let body = EofBody::decode(&raw, &header)?; + Ok(Self { header, body, raw }) + } + *) + Definition decode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ raw ] => + ltac:(M.monadic + (let raw := M.alloc (| raw |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ]; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + "decode", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ raw ] + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::eof::Eof"; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let header := M.copy (| ฮณ0_0 |) in + let~ body := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::eof::body::EofBody"; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + "decode", + [] + |), + [ raw; header ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::eof::Eof"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructRecord + "revm_primitives::bytecode::eof::Eof" + [ + ("header", M.read (| header |)); + ("body", M.read (| body |)); + ("raw", M.read (| raw |)) + ] + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_decode : M.IsAssociatedFunction Self "decode" decode. + End Impl_revm_primitives_bytecode_eof_Eof. + + (* + Enum EofDecodeError + { + ty_params := []; + variants := + [ + { + name := "MissingInput"; + item := StructTuple []; + discriminant := None; + }; + { + name := "MissingBodyWithoutData"; + item := StructTuple []; + discriminant := None; + }; + { + name := "DanglingData"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidTypesSection"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidTypesSectionSize"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidEOFMagicNumber"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidEOFVersion"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidTypesKind"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidCodeKind"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidTerminalByte"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidDataKind"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidKindAfterCode"; + item := StructTuple []; + discriminant := None; + }; + { + name := "MismatchCodeAndTypesSize"; + item := StructTuple []; + discriminant := None; + }; + { + name := "NonSizes"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ShortInputForSizes"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ZeroSize"; + item := StructTuple []; + discriminant := None; + }; + { + name := "TooManyCodeSections"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ZeroCodeSections"; + item := StructTuple []; + discriminant := None; + }; + { + name := "TooManyContainerSections"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::MissingInput" + |) in + M.alloc (| M.read (| Value.String "MissingInput" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::MissingBodyWithoutData" + |) in + M.alloc (| M.read (| Value.String "MissingBodyWithoutData" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::DanglingData" + |) in + M.alloc (| M.read (| Value.String "DanglingData" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::InvalidTypesSection" + |) in + M.alloc (| M.read (| Value.String "InvalidTypesSection" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::InvalidTypesSectionSize" + |) in + M.alloc (| M.read (| Value.String "InvalidTypesSectionSize" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::InvalidEOFMagicNumber" + |) in + M.alloc (| M.read (| Value.String "InvalidEOFMagicNumber" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::InvalidEOFVersion" + |) in + M.alloc (| M.read (| Value.String "InvalidEOFVersion" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::InvalidTypesKind" + |) in + M.alloc (| M.read (| Value.String "InvalidTypesKind" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::InvalidCodeKind" + |) in + M.alloc (| M.read (| Value.String "InvalidCodeKind" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::InvalidTerminalByte" + |) in + M.alloc (| M.read (| Value.String "InvalidTerminalByte" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::InvalidDataKind" + |) in + M.alloc (| M.read (| Value.String "InvalidDataKind" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::InvalidKindAfterCode" + |) in + M.alloc (| M.read (| Value.String "InvalidKindAfterCode" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::MismatchCodeAndTypesSize" + |) in + M.alloc (| M.read (| Value.String "MismatchCodeAndTypesSize" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::NonSizes" + |) in + M.alloc (| M.read (| Value.String "NonSizes" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::ShortInputForSizes" + |) in + M.alloc (| M.read (| Value.String "ShortInputForSizes" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::ZeroSize" + |) in + M.alloc (| M.read (| Value.String "ZeroSize" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::TooManyCodeSections" + |) in + M.alloc (| M.read (| Value.String "TooManyCodeSections" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::ZeroCodeSections" + |) in + M.alloc (| M.read (| Value.String "ZeroCodeSections" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::bytecode::eof::EofDecodeError::TooManyContainerSections" + |) in + M.alloc (| M.read (| Value.String "TooManyContainerSections" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_EofDecodeError. + + Module Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_EofDecodeError. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_EofDecodeError. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_EofDecodeError. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_EofDecodeError. + + Module Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_EofDecodeError. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "isize", + [ Ty.path "isize" ], + "partial_cmp", + [] + |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_bytecode_eof_EofDecodeError. + + Module Impl_core_cmp_Ord_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::bytecode::eof::EofDecodeError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "isize", [], "cmp", [] |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_bytecode_eof_EofDecodeError. + + Module Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_EofDecodeError. + + Module Impl_core_marker_Copy_for_revm_primitives_bytecode_eof_EofDecodeError. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::EofDecodeError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_bytecode_eof_EofDecodeError. + End eof. +End bytecode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/body.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/body.md new file mode 100644 index 00000000..6abdb4b2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/body.md @@ -0,0 +1,2775 @@ +# ๐Ÿ“ body.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/bytecode/eof/body.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module bytecode. + Module eof. + Module body. + (* StructRecord + { + name := "EofBody"; + ty_params := []; + fields := + [ + ("types_section", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ]); + ("code_section", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "alloc::alloc::Global" ]); + ("container_section", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "alloc::alloc::Global" ]); + ("data_section", Ty.path "alloy_primitives::bytes_::Bytes"); + ("is_data_filled", Ty.path "bool") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_body_EofBody. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::body::EofBody". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::bytecode::eof::body::EofBody" + [ + ("types_section", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |) + ] + |)); + ("code_section", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |) + ] + |)); + ("container_section", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |) + ] + |)); + ("data_section", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |) + ] + |)); + ("is_data_filled", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "is_data_filled" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_body_EofBody. + + Module Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_body_EofBody. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::body::EofBody". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field5_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "EofBody" |); + M.read (| Value.String "types_section" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |)); + M.read (| Value.String "code_section" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |)); + M.read (| Value.String "container_section" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |)); + M.read (| Value.String "data_section" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |)); + M.read (| Value.String "is_data_filled" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "is_data_filled" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_body_EofBody. + + Module Impl_core_default_Default_for_revm_primitives_bytecode_eof_body_EofBody. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::body::EofBody". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::bytecode::eof::body::EofBody" + [ + ("types_section", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)); + ("code_section", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)); + ("container_section", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)); + ("data_section", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "default", + [] + |), + [] + |)); + ("is_data_filled", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_bytecode_eof_body_EofBody. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_body_EofBody. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::body::EofBody". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_body_EofBody. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_body_EofBody. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::body::EofBody". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "is_data_filled" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::body::EofBody", + "is_data_filled" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_body_EofBody. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_body_EofBody. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::body::EofBody". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_body_EofBody. + + Module Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_body_EofBody. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::body::EofBody". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_body_EofBody. + + Module Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_body_EofBody. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::body::EofBody". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "bool", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "is_data_filled" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_body_EofBody. + + Module Impl_revm_primitives_bytecode_eof_body_EofBody. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::body::EofBody". + + (* + pub fn code(&self, index: usize) -> Option<&Bytes> { + self.code_section.get(index) + } + *) + Definition code (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "get", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |) + ] + |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_code : M.IsAssociatedFunction Self "code" code. + + (* + pub fn into_eof(self) -> Eof { + // TODO add bounds checks. + let header = EofHeader { + types_size: self.types_section.len() as u16 * 4, + code_sizes: self.code_section.iter().map(|x| x.len() as u16).collect(), + container_sizes: self + .container_section + .iter() + .map(|x| x.len() as u16) + .collect(), + data_size: self.data_section.len() as u16, + sum_code_sizes: self.code_section.iter().map(|x| x.len()).sum(), + sum_container_sizes: self.container_section.iter().map(|x| x.len()).sum(), + }; + let mut buffer = Vec::new(); + header.encode(&mut buffer); + self.encode(&mut buffer); + Eof { + header, + body: self, + raw: buffer.into(), + } + } + *) + Definition into_eof (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ header := + M.alloc (| + Value.StructRecord + "revm_primitives::bytecode::eof::header::EofHeader" + [ + ("types_size", + BinOp.Wrap.mul + Integer.U16 + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |) + ] + |))) + (Value.Integer 4)); + ("code_sizes", + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + ] + (Ty.path "u16") + ], + [], + "collect", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + [], + "map", + [ + Ty.path "u16"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + ] + (Ty.path "u16") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |) + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let x := M.copy (| ฮณ |) in + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path + "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| x |) ] + |) + ] + |)))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |)); + ("container_sizes", + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + ] + (Ty.path "u16") + ], + [], + "collect", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + [], + "map", + [ + Ty.path "u16"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + ] + (Ty.path "u16") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |) + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let x := M.copy (| ฮณ |) in + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path + "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| x |) ] + |) + ] + |)))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |)); + ("data_size", + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |) + ] + |) + ] + |))); + ("sum_code_sizes", + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + ] + (Ty.path "usize") + ], + [], + "sum", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + [], + "map", + [ + Ty.path "usize"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + ] + (Ty.path "usize") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |) + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let x := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| x |) ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |)); + ("sum_container_sizes", + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + ] + (Ty.path "usize") + ], + [], + "sum", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + [], + "map", + [ + Ty.path "usize"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + ] + (Ty.path "usize") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |) + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let x := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| x |) ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |)) + ] + |) in + let~ buffer := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + "encode", + [] + |), + [ header; buffer ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + "encode", + [] + |), + [ self; buffer ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm_primitives::bytecode::eof::Eof" + [ + ("header", M.read (| header |)); + ("body", M.read (| self |)); + ("raw", + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "into", + [] + |), + [ M.read (| buffer |) ] + |)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_eof : M.IsAssociatedFunction Self "into_eof" into_eof. + + (* + pub fn encode(&self, buffer: &mut Vec) { + for types_section in &self.types_section { + types_section.encode(buffer); + } + + for code_section in &self.code_section { + buffer.extend_from_slice(code_section); + } + + for container_section in &self.container_section { + buffer.extend_from_slice(container_section); + } + + buffer.extend_from_slice(&self.data_section); + } + *) + Definition encode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; buffer ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let buffer := M.alloc (| buffer |) in + M.read (| + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "into_iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let types_section := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection", + "encode", + [] + |), + [ M.read (| types_section |); M.read (| buffer |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "into_iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let code_section := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" + ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| code_section |) ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "into_iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let container_section := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" + ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| container_section |) ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |) + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_encode : M.IsAssociatedFunction Self "encode" encode. + + (* + pub fn decode(input: &Bytes, header: &EofHeader) -> Result { + let header_len = header.size(); + let partial_body_len = + header.sum_code_sizes + header.sum_container_sizes + header.types_size as usize; + let full_body_len = partial_body_len + header.data_size as usize; + + if input.len() < header_len + partial_body_len { + return Err(EofDecodeError::MissingBodyWithoutData); + } + + if input.len() > header_len + full_body_len { + return Err(EofDecodeError::DanglingData); + } + + let mut body = EofBody::default(); + + let mut types_input = &input[header_len..]; + for _ in 0..header.types_count() { + let (types_section, local_input) = TypesSection::decode(types_input)?; + types_input = local_input; + body.types_section.push(types_section); + } + + // extract code section + let mut start = header_len + header.types_size as usize; + for size in header.code_sizes.iter().map(|x| *x as usize) { + body.code_section.push(input.slice(start..start + size)); + start += size; + } + + // extract container section + for size in header.container_sizes.iter().map(|x| *x as usize) { + body.container_section + .push(input.slice(start..start + size)); + start += size; + } + + body.data_section = input.slice(start..); + body.is_data_filled = body.data_section.len() == header.data_size as usize; + + Ok(body) + } + *) + Definition decode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input; header ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + let header := M.alloc (| header |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ header_len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + "size", + [] + |), + [ M.read (| header |) ] + |) + |) in + let~ partial_body_len := + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| header |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_code_sizes" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| header |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_container_sizes" + |) + |))) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| header |), + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |) + |))) + |) in + let~ full_body_len := + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| partial_body_len |)) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| header |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + |))) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |)) + (BinOp.Wrap.add + Integer.Usize + (M.read (| header_len |)) + (M.read (| partial_body_len |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::MissingBodyWithoutData" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |)) + (BinOp.Wrap.add + Integer.Usize + (M.read (| header_len |)) + (M.read (| full_body_len |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::DanglingData" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ body := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::eof::body::EofBody", + [], + "default", + [] + |), + [] + |) + |) in + let~ types_input := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::RangeFrom") [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", M.read (| header_len |)) ] + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader", + "types_count", + [] + |), + [ M.read (| header |) ] + |)) + ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection", + "decode", + [] + |), + [ M.read (| types_input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm_primitives::bytecode::eof::body::EofBody"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let types_section := M.copy (| ฮณ0_0 |) in + let local_input := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + types_input, + M.read (| local_input |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + body, + "revm_primitives::bytecode::eof::body::EofBody", + "types_section" + |); + M.read (| types_section |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ start := + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (M.read (| header_len |)) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| header |), + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |) + |))) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply (Ty.path "core::slice::iter::Iter") [ Ty.path "u16" ]; + Ty.function + [ Ty.tuple [ Ty.apply (Ty.path "&") [ Ty.path "u16" ] ] ] + (Ty.path "usize") + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply (Ty.path "core::slice::iter::Iter") [ Ty.path "u16" ], + [], + "map", + [ + Ty.path "usize"; + Ty.function + [ Ty.tuple [ Ty.apply (Ty.path "&") [ Ty.path "u16" ] ] ] + (Ty.path "usize") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u16" ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| header |), + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |) + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let x := M.copy (| ฮณ |) in + M.rust_cast (M.read (| M.read (| x |) |)))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "u16" ]; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "&") [ Ty.path "u16" ] ] + ] + (Ty.path "usize") + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let size := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + body, + "revm_primitives::bytecode::eof::body::EofBody", + "code_section" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "slice", + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| start |)); + ("end_", + BinOp.Wrap.add + Integer.Usize + (M.read (| start |)) + (M.read (| size |))) + ] + ] + |) + ] + |) + |) in + let~ _ := + let ฮฒ := start in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.read (| size |)) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply (Ty.path "core::slice::iter::Iter") [ Ty.path "u16" ]; + Ty.function + [ Ty.tuple [ Ty.apply (Ty.path "&") [ Ty.path "u16" ] ] ] + (Ty.path "usize") + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply (Ty.path "core::slice::iter::Iter") [ Ty.path "u16" ], + [], + "map", + [ + Ty.path "usize"; + Ty.function + [ Ty.tuple [ Ty.apply (Ty.path "&") [ Ty.path "u16" ] ] ] + (Ty.path "usize") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u16" ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| header |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |) + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let x := M.copy (| ฮณ |) in + M.rust_cast (M.read (| M.read (| x |) |)))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "u16" ]; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "&") [ Ty.path "u16" ] ] + ] + (Ty.path "usize") + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let size := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + body, + "revm_primitives::bytecode::eof::body::EofBody", + "container_section" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "slice", + [ + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ] + ] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::Range" + [ + ("start", M.read (| start |)); + ("end_", + BinOp.Wrap.add + Integer.Usize + (M.read (| start |)) + (M.read (| size |))) + ] + ] + |) + ] + |) + |) in + let~ _ := + let ฮฒ := start in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.read (| size |)) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + body, + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "slice", + [ Ty.apply (Ty.path "core::ops::range::RangeFrom") [ Ty.path "usize" ] ] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", M.read (| start |)) ] + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + body, + "revm_primitives::bytecode::eof::body::EofBody", + "is_data_filled" + |), + BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + body, + "revm_primitives::bytecode::eof::body::EofBody", + "data_section" + |) + ] + |) + ] + |)) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| header |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + |))) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ M.read (| body |) ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_decode : M.IsAssociatedFunction Self "decode" decode. + End Impl_revm_primitives_bytecode_eof_body_EofBody. + End body. + End eof. +End bytecode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/decode_helpers.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/decode_helpers.md new file mode 100644 index 00000000..8aa7fbd6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/decode_helpers.md @@ -0,0 +1,229 @@ +# ๐Ÿ“ decode_helpers.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/bytecode/eof/decode_helpers.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module bytecode. + Module eof. + Module decode_helpers. + (* + pub(crate) fn consume_u8(input: &[u8]) -> Result<(&[u8], u8), EofDecodeError> { + if input.is_empty() { + return Err(EofDecodeError::MissingInput); + } + Ok((&input[1..], input[0])) + } + *) + Definition consume_u8 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "is_empty", + [] + |), + [ M.read (| input |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::MissingInput" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeFrom") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", Value.Integer 1) ] + ] + |); + M.read (| + M.SubPointer.get_array_field (| + M.read (| input |), + M.alloc (| Value.Integer 0 |) + |) + |) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_consume_u8 : + M.IsFunction "revm_primitives::bytecode::eof::decode_helpers::consume_u8" consume_u8. + + (* + pub(crate) fn consume_u16(input: &[u8]) -> Result<(&[u8], u16), EofDecodeError> { + if input.len() < 2 { + return Err(EofDecodeError::MissingInput); + } + let (int_bytes, rest) = input.split_at(2); + Ok((rest, u16::from_be_bytes([int_bytes[0], int_bytes[1]]))) + } + *) + Definition consume_u16 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| input |) ] + |)) + (Value.Integer 2) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::MissingInput" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "split_at", + [] + |), + [ M.read (| input |); Value.Integer 2 ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let int_bytes := M.copy (| ฮณ0_0 |) in + let rest := M.copy (| ฮณ0_1 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| rest |); + M.call_closure (| + M.get_associated_function (| + Ty.path "u16", + "from_be_bytes", + [] + |), + [ + Value.Array + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| int_bytes |), + M.alloc (| Value.Integer 0 |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + M.read (| int_bytes |), + M.alloc (| Value.Integer 1 |) + |) + |) + ] + ] + |) + ] + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_consume_u16 : + M.IsFunction "revm_primitives::bytecode::eof::decode_helpers::consume_u16" consume_u16. + End decode_helpers. + End eof. +End bytecode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/header.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/header.md new file mode 100644 index 00000000..78bf417e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/header.md @@ -0,0 +1,4345 @@ +# ๐Ÿ“ header.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/bytecode/eof/header.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module bytecode. + Module eof. + Module header. + (* StructRecord + { + name := "EofHeader"; + ty_params := []; + fields := + [ + ("types_size", Ty.path "u16"); + ("code_sizes", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ]); + ("container_sizes", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ]); + ("data_size", Ty.path "u16"); + ("sum_code_sizes", Ty.path "usize"); + ("sum_container_sizes", Ty.path "usize") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_header_EofHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::header::EofHeader". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::bytecode::eof::header::EofHeader" + [ + ("types_size", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u16", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |) + ] + |)); + ("code_sizes", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |) + ] + |)); + ("container_sizes", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |) + ] + |)); + ("data_size", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u16", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + ] + |)); + ("sum_code_sizes", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "usize", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_code_sizes" + |) + ] + |)); + ("sum_container_sizes", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "usize", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_container_sizes" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_header_EofHeader. + + Module Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_header_EofHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::header::EofHeader". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "types_size" |); + M.read (| Value.String "code_sizes" |); + M.read (| Value.String "container_sizes" |); + M.read (| Value.String "data_size" |); + M.read (| Value.String "sum_code_sizes" |); + M.read (| Value.String "sum_container_sizes" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_code_sizes" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_container_sizes" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "EofHeader" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_header_EofHeader. + + Module Impl_core_default_Default_for_revm_primitives_bytecode_eof_header_EofHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::header::EofHeader". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::bytecode::eof::header::EofHeader" + [ + ("types_size", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u16", + [], + "default", + [] + |), + [] + |)); + ("code_sizes", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [], + "default", + [] + |), + [] + |)); + ("container_sizes", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [], + "default", + [] + |), + [] + |)); + ("data_size", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u16", + [], + "default", + [] + |), + [] + |)); + ("sum_code_sizes", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "usize", + [], + "default", + [] + |), + [] + |)); + ("sum_container_sizes", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "usize", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_bytecode_eof_header_EofHeader. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_header_EofHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::header::EofHeader". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_header_EofHeader. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_header_EofHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::header::EofHeader". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |) + |)), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_code_sizes" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_code_sizes" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_container_sizes" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_container_sizes" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_header_EofHeader. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_header_EofHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::header::EofHeader". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_header_EofHeader. + + Module Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_header_EofHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::header::EofHeader". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_header_EofHeader. + + Module Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_header_EofHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::header::EofHeader". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u16", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u16", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "usize", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_code_sizes" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "usize", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_container_sizes" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_header_EofHeader. + + Definition value_KIND_TERMINAL : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 0 |))). + + Definition value_KIND_TYPES : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 1 |))). + + Definition value_KIND_CODE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 2 |))). + + Definition value_KIND_CONTAINER : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 3 |))). + + Definition value_KIND_DATA : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 4 |))). + + (* + fn consume_header_section_size(input: &[u8]) -> Result<(&[u8], Vec, usize), EofDecodeError> { + // num_sections 2 bytes 0x0001-0xFFFF + // 16-bit unsigned big-endian integer denoting the number of the sections + let (input, num_sections) = consume_u16(input)?; + if num_sections == 0 { + return Err(EofDecodeError::NonSizes); + } + let byte_size = (num_sections * 2) as usize; + if input.len() < byte_size { + return Err(EofDecodeError::ShortInputForSizes); + } + let mut sizes = Vec::with_capacity(num_sections as usize); + let mut sum = 0; + for i in 0..num_sections as usize { + // size 2 bytes 0x0001-0xFFFF + // 16-bit unsigned big-endian integer denoting the length of the section content + let code_size = u16::from_be_bytes([input[i * 2], input[i * 2 + 1]]); + if code_size == 0 { + return Err(EofDecodeError::ZeroSize); + } + sum += code_size as usize; + sizes.push(code_size); + } + + Ok((&input[byte_size..], sizes, sum)) + } + *) + Definition consume_header_section_size (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]; + Ty.path "u16" + ]; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u16", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ]; + Ty.path "usize" + ]; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let input := M.copy (| ฮณ0_0 |) in + let num_sections := M.copy (| ฮณ0_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| num_sections |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::NonSizes" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ byte_size := + M.alloc (| + M.rust_cast + (BinOp.Wrap.mul + Integer.U16 + (M.read (| num_sections |)) + (Value.Integer 2)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ M.read (| input |) ] + |)) + (M.read (| byte_size |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::ShortInputForSizes" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ sizes := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + "with_capacity", + [] + |), + [ M.rust_cast (M.read (| num_sections |)) ] + |) + |) in + let~ sum := M.alloc (| Value.Integer 0 |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "into_iter", + [] + |), + [ + Value.StructRecord + "core::ops::range::Range" + [ + ("start", Value.Integer 0); + ("end_", M.rust_cast (M.read (| num_sections |))) + ] + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let i := M.copy (| ฮณ0_0 |) in + let~ code_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "u16", + "from_be_bytes", + [] + |), + [ + Value.Array + [ + M.read (| + M.SubPointer.get_array_field (| + M.read (| input |), + M.alloc (| + BinOp.Wrap.mul + Integer.Usize + (M.read (| i |)) + (Value.Integer 2) + |) + |) + |); + M.read (| + M.SubPointer.get_array_field (| + M.read (| input |), + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.mul + Integer.Usize + (M.read (| i |)) + (Value.Integer 2)) + (Value.Integer 1) + |) + |) + |) + ] + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| code_size |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::ZeroSize" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + let ฮฒ := sum in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.rust_cast (M.read (| code_size |))) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "u16"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ sizes; M.read (| code_size |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeFrom") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.read (| input |); + Value.StructRecord + "core::ops::range::RangeFrom" + [ ("start", M.read (| byte_size |)) ] + ] + |); + M.read (| sizes |); + M.read (| sum |) + ] + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_consume_header_section_size : + M.IsFunction + "revm_primitives::bytecode::eof::header::consume_header_section_size" + consume_header_section_size. + + Module Impl_revm_primitives_bytecode_eof_header_EofHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::eof::header::EofHeader". + + (* + pub fn size(&self) -> usize { + let optional_container_sizes = if self.container_sizes.is_empty() { + 0 + } else { + 3 + self.container_sizes.len() * 2 + }; + 13 + self.code_sizes.len() * 2 + optional_container_sizes + } + *) + Definition size (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ optional_container_sizes := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| Value.Integer 0 |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + BinOp.Wrap.add + Integer.Usize + (Value.Integer 3) + (BinOp.Wrap.mul + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |) + ] + |)) + (Value.Integer 2)) + |))) + ] + |) + |) in + M.alloc (| + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (Value.Integer 13) + (BinOp.Wrap.mul + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |) + ] + |)) + (Value.Integer 2))) + (M.read (| optional_container_sizes |)) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_size : M.IsAssociatedFunction Self "size" size. + + (* + pub fn types_count(&self) -> usize { + self.types_size as usize / 4 + } + *) + Definition types_count (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.div + Integer.Usize + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |) + |))) + (Value.Integer 4))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_types_count : + M.IsAssociatedFunction Self "types_count" types_count. + + (* + pub fn body_size(&self) -> usize { + self.sum_code_sizes + self.sum_container_sizes + self.data_size as usize + } + *) + Definition body_size (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_code_sizes" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_container_sizes" + |) + |))) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + |))))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_body_size : M.IsAssociatedFunction Self "body_size" body_size. + + (* + pub fn eof_size(&self) -> usize { + self.size() + self.body_size() + } + *) + Definition eof_size (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.add + Integer.Usize + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + "size", + [] + |), + [ M.read (| self |) ] + |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + "body_size", + [] + |), + [ M.read (| self |) ] + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_eof_size : M.IsAssociatedFunction Self "eof_size" eof_size. + + (* + pub fn encode(&self, buffer: &mut Vec) { + // magic 2 bytes 0xEF00 EOF prefix + buffer.extend_from_slice(&0xEF00u16.to_be_bytes()); + // version 1 byte 0x01 EOF version + buffer.push(0x01); + // kind_types 1 byte 0x01 kind marker for types size section + buffer.push(KIND_TYPES); + // types_size 2 bytes 0x0004-0xFFFF + buffer.extend_from_slice(&self.types_size.to_be_bytes()); + // kind_code 1 byte 0x02 kind marker for code size section + buffer.push(KIND_CODE); + // code_sections_sizes + buffer.extend_from_slice(&(self.code_sizes.len() as u16).to_be_bytes()); + for size in &self.code_sizes { + buffer.extend_from_slice(&size.to_be_bytes()); + } + // kind_container_or_data 1 byte 0x03 or 0x04 kind marker for container size section or data size section + if self.container_sizes.is_empty() { + buffer.push(KIND_DATA); + } else { + buffer.push(KIND_CONTAINER); + // container_sections_sizes + buffer.extend_from_slice(&(self.container_sizes.len() as u16).to_be_bytes()); + for size in &self.container_sizes { + buffer.extend_from_slice(&size.to_be_bytes()); + } + // kind_data 1 byte 0x04 kind marker for data size section + buffer.push(KIND_DATA); + } + // data_size 2 bytes 0x0000-0xFFFF 16-bit unsigned big-endian integer denoting the length of the data section content + buffer.extend_from_slice(&self.data_size.to_be_bytes()); + // terminator 1 byte 0x00 marks the end of the EofHeader + buffer.push(KIND_TERMINAL); + } + *) + Definition encode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; buffer ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let buffer := M.alloc (| buffer |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u16", "to_be_bytes", [] |), + [ Value.Integer 61184 ] + |) + |)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ M.read (| buffer |); Value.Integer 1 ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.read (| buffer |); + M.read (| + M.get_constant (| "revm_primitives::bytecode::eof::header::KIND_TYPES" |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u16", "to_be_bytes", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |) + |) + ] + |) + |)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.read (| buffer |); + M.read (| + M.get_constant (| "revm_primitives::bytecode::eof::header::KIND_CODE" |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u16", "to_be_bytes", [] |), + [ + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |) + ] + |)) + ] + |) + |)) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ] + ], + [], + "into_iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "u16" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let size := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" + ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "u16", + "to_be_bytes", + [] + |), + [ M.read (| M.read (| size |) |) ] + |) + |)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.read (| buffer |); + M.read (| + M.get_constant (| + "revm_primitives::bytecode::eof::header::KIND_DATA" + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.read (| buffer |); + M.read (| + M.get_constant (| + "revm_primitives::bytecode::eof::header::KIND_CONTAINER" + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "u16", + "to_be_bytes", + [] + |), + [ + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |) + ] + |)) + ] + |) + |)) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u16"; Ty.path "alloc::alloc::Global" ] + ], + [], + "into_iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "u16" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let size := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "u8"; + Ty.path "alloc::alloc::Global" + ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "u16", + "to_be_bytes", + [] + |), + [ M.read (| M.read (| size |) |) ] + |) + |)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.read (| buffer |); + M.read (| + M.get_constant (| + "revm_primitives::bytecode::eof::header::KIND_DATA" + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u16", "to_be_bytes", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |) + |) + ] + |) + |)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.read (| buffer |); + M.read (| + M.get_constant (| + "revm_primitives::bytecode::eof::header::KIND_TERMINAL" + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_encode : M.IsAssociatedFunction Self "encode" encode. + + (* + pub fn decode(input: &[u8]) -> Result<(Self, &[u8]), EofDecodeError> { + let mut header = EofHeader::default(); + + // magic 2 bytes 0xEF00 EOF prefix + let (input, kind) = consume_u16(input)?; + if kind != 0xEF00 { + return Err(EofDecodeError::InvalidEOFMagicNumber); + } + + // version 1 byte 0x01 EOF version + let (input, version) = consume_u8(input)?; + if version != 0x01 { + return Err(EofDecodeError::InvalidEOFVersion); + } + + // kind_types 1 byte 0x01 kind marker for types size section + let (input, kind_types) = consume_u8(input)?; + if kind_types != KIND_TYPES { + return Err(EofDecodeError::InvalidTypesKind); + } + + // types_size 2 bytes 0x0004-0xFFFF + // 16-bit unsigned big-endian integer denoting the length of the type section content + let (input, types_size) = consume_u16(input)?; + header.types_size = types_size; + + if header.types_size % 4 != 0 { + return Err(EofDecodeError::InvalidTypesSection); + } + + // kind_code 1 byte 0x02 kind marker for code size section + let (input, kind_types) = consume_u8(input)?; + if kind_types != KIND_CODE { + return Err(EofDecodeError::InvalidCodeKind); + } + + // code_sections_sizes + let (input, sizes, sum) = consume_header_section_size(input)?; + + if sizes.len() > 1024 { + return Err(EofDecodeError::TooManyCodeSections); + } + + if sizes.is_empty() { + return Err(EofDecodeError::ZeroCodeSections); + } + + if sizes.len() != (types_size / 4) as usize { + return Err(EofDecodeError::MismatchCodeAndTypesSize); + } + + header.code_sizes = sizes; + header.sum_code_sizes = sum; + + let (input, kind_container_or_data) = consume_u8(input)?; + + let input = match kind_container_or_data { + KIND_CONTAINER => { + // container_sections_sizes + let (input, sizes, sum) = consume_header_section_size(input)?; + // the number of container sections must not exceed 256 + if sizes.len() > 256 { + return Err(EofDecodeError::TooManyContainerSections); + } + header.container_sizes = sizes; + header.sum_container_sizes = sum; + let (input, kind_data) = consume_u8(input)?; + if kind_data != KIND_DATA { + return Err(EofDecodeError::InvalidDataKind); + } + input + } + KIND_DATA => input, + _ => return Err(EofDecodeError::InvalidKindAfterCode), + }; + + // data_size 2 bytes 0x0000-0xFFFF 16-bit + // unsigned big-endian integer denoting the length + // of the data section content (for not yet deployed + // containers this can be more than the actual content, see Data Section Lifecycle) + let (input, data_size) = consume_u16(input)?; + header.data_size = data_size; + + // terminator 1 byte 0x00 marks the end of the EofHeader + let (input, terminator) = consume_u8(input)?; + if terminator != KIND_TERMINAL { + return Err(EofDecodeError::InvalidTerminalByte); + } + + Ok((header, input)) + } + *) + Definition decode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ header := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::eof::header::EofHeader", + [], + "default", + [] + |), + [] + |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]; + Ty.path "u16" + ]; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u16", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let input := M.copy (| ฮณ0_0 |) in + let kind := M.copy (| ฮณ0_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne (M.read (| kind |)) (Value.Integer 61184) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidEOFMagicNumber" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]; + Ty.path "u8" + ]; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u8", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let input := M.copy (| ฮณ0_0 |) in + let version := M.copy (| ฮณ0_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| version |)) + (Value.Integer 1) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidEOFVersion" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ]; + Ty.path "u8" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u8", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let input := M.copy (| ฮณ0_0 |) in + let kind_types := M.copy (| ฮณ0_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| kind_types |)) + (M.read (| + M.get_constant (| + "revm_primitives::bytecode::eof::header::KIND_TYPES" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidTypesKind" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ]; + Ty.path "u16" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u16", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let input := M.copy (| ฮณ0_0 |) in + let types_size := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + header, + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |), + M.read (| types_size |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (BinOp.Wrap.rem + Integer.U16 + (M.read (| + M.SubPointer.get_struct_record_field (| + header, + "revm_primitives::bytecode::eof::header::EofHeader", + "types_size" + |) + |)) + (Value.Integer 4)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidTypesSection" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ]; + Ty.path "u8" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u8", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let input := M.copy (| ฮณ0_0 |) in + let kind_types := M.copy (| ฮณ0_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| + kind_types + |)) + (M.read (| + M.get_constant (| + "revm_primitives::bytecode::eof::header::KIND_CODE" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidCodeKind" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path + "slice") + [ Ty.path "u8" ] + ]; + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path "u16"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path "usize" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::header::consume_header_section_size", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := + M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let ฮณ0_2 := + M.SubPointer.get_tuple_field (| + ฮณ, + 2 + |) in + let input := + M.copy (| ฮณ0_0 |) in + let sizes := + M.copy (| ฮณ0_1 |) in + let sum := M.copy (| ฮณ0_2 |) in + let~ _ := + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "u16"; + Ty.path + "alloc::alloc::Global" + ], + "len", + [] + |), + [ sizes ] + |)) + (Value.Integer + 1024) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::TooManyCodeSections" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "u16"; + Ty.path + "alloc::alloc::Global" + ], + "is_empty", + [] + |), + [ sizes ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::ZeroCodeSections" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "u16"; + Ty.path + "alloc::alloc::Global" + ], + "len", + [] + |), + [ sizes ] + |)) + (M.rust_cast + (BinOp.Wrap.div + Integer.U16 + (M.read (| + types_size + |)) + (Value.Integer + 4))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::MismatchCodeAndTypesSize" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + header, + "revm_primitives::bytecode::eof::header::EofHeader", + "code_sizes" + |), + M.read (| sizes |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + header, + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_code_sizes" + |), + M.read (| sum |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ]; + Ty.path "u8" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u8", + [] + |), + [ M.read (| input |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := + M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let input := + M.copy (| ฮณ0_0 |) in + let + kind_container_or_data := + M.copy (| ฮณ0_1 |) in + let~ input := + M.copy (| + M.match_operator (| + kind_container_or_data, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Integer + 3 + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ]; + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "u16"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "usize" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::header::consume_header_section_size", + [] + |), + [ + M.read (| + input + |) + ] + |) + ] + |) + |), + [ + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let + residual := + M.copy (| + ฮณ0_0 + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let + val := + M.copy (| + ฮณ0_0 + |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let + ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let + ฮณ0_2 := + M.SubPointer.get_tuple_field (| + ฮณ, + 2 + |) in + let + input := + M.copy (| + ฮณ0_0 + |) in + let + sizes := + M.copy (| + ฮณ0_1 + |) in + let + sum := + M.copy (| + ฮณ0_2 + |) in + let~ + _ := + M.match_operator (| + M.alloc (| + Value.Tuple + [] + |), + [ + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "u16"; + Ty.path + "alloc::alloc::Global" + ], + "len", + [] + |), + [ + sizes + ] + |)) + (Value.Integer + 256) + |)) in + let + _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Bool + true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::TooManyContainerSections" + [] + ] + |) + |) + |) + |))); + fun + ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple + [] + |))) + ] + |) in + let~ + _ := + M.write (| + M.SubPointer.get_struct_record_field (| + header, + "revm_primitives::bytecode::eof::header::EofHeader", + "container_sizes" + |), + M.read (| + sizes + |) + |) in + let~ + _ := + M.write (| + M.SubPointer.get_struct_record_field (| + header, + "revm_primitives::bytecode::eof::header::EofHeader", + "sum_container_sizes" + |), + M.read (| + sum + |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ]; + Ty.path + "u8" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u8", + [] + |), + [ + M.read (| + input + |) + ] + |) + ] + |) + |), + [ + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let + residual := + M.copy (| + ฮณ0_0 + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let + val := + M.copy (| + ฮณ0_0 + |) in + val)) + ] + |), + [ + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let + ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let + input := + M.copy (| + ฮณ0_0 + |) in + let + kind_data := + M.copy (| + ฮณ0_1 + |) in + let~ + _ := + M.match_operator (| + M.alloc (| + Value.Tuple + [] + |), + [ + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| + kind_data + |)) + (M.read (| + M.get_constant (| + "revm_primitives::bytecode::eof::header::KIND_DATA" + |) + |)) + |)) in + let + _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Bool + true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidDataKind" + [] + ] + |) + |) + |) + |))); + fun + ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple + [] + |))) + ] + |) in + input)) + ] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Integer + 4 + |) in + M.alloc (| + M.read (| + input + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidKindAfterCode" + [] + ] + |) + |) + |) + |))) + ] + |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ]; + Ty.path + "u16" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u16", + [] + |), + [ + M.read (| + input + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let + residual := + M.copy (| + ฮณ0_0 + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| + ฮณ0_0 + |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let input := + M.copy (| + ฮณ0_0 + |) in + let data_size := + M.copy (| + ฮณ0_1 + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + header, + "revm_primitives::bytecode::eof::header::EofHeader", + "data_size" + |), + M.read (| + data_size + |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ]; + Ty.path + "u8" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u8", + [] + |), + [ + M.read (| + input + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let + residual := + M.copy (| + ฮณ0_0 + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::header::EofHeader"; + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "slice") + [ + Ty.path + "u8" + ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let + val := + M.copy (| + ฮณ0_0 + |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let + ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let + input := + M.copy (| + ฮณ0_0 + |) in + let + terminator := + M.copy (| + ฮณ0_1 + |) in + let~ + _ := + M.match_operator (| + M.alloc (| + Value.Tuple + [] + |), + [ + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| + terminator + |)) + (M.read (| + M.get_constant (| + "revm_primitives::bytecode::eof::header::KIND_TERMINAL" + |) + |)) + |)) in + let + _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Bool + true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidTerminalByte" + [] + ] + |) + |) + |) + |))); + fun + ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple + [] + |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| + header + |); + M.read (| + input + |) + ] + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_decode : M.IsAssociatedFunction Self "decode" decode. + End Impl_revm_primitives_bytecode_eof_header_EofHeader. + End header. + End eof. +End bytecode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/types_section.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/types_section.md new file mode 100644 index 00000000..b45d9b36 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/eof/types_section.md @@ -0,0 +1,1136 @@ +# ๐Ÿ“ types_section.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/bytecode/eof/types_section.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module bytecode. + Module eof. + Module types_section. + (* StructRecord + { + name := "TypesSection"; + ty_params := []; + fields := + [ ("inputs", Ty.path "u8"); ("outputs", Ty.path "u8"); ("max_stack_size", Ty.path "u16") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "TypesSection" |); + M.read (| Value.String "inputs" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |)); + M.read (| Value.String "outputs" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |)); + M.read (| Value.String "max_stack_size" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_bytecode_eof_types_section_TypesSection. + + Module Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_bytecode_eof_types_section_TypesSection. + + Module Impl_core_default_Default_for_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::bytecode::eof::types_section::TypesSection" + [ + ("inputs", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u8", + [], + "default", + [] + |), + [] + |)); + ("outputs", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u8", + [], + "default", + [] + |), + [] + |)); + ("max_stack_size", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u16", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_bytecode_eof_types_section_TypesSection. + + Module Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u8", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u8", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u16", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_bytecode_eof_types_section_TypesSection. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_eof_types_section_TypesSection. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_eof_types_section_TypesSection. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_eof_types_section_TypesSection. + + Module Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_bytecode_eof_types_section_TypesSection. + + Module Impl_core_marker_Copy_for_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_bytecode_eof_types_section_TypesSection. + + Module Impl_revm_primitives_bytecode_eof_types_section_TypesSection. + Definition Self : Ty.t := + Ty.path "revm_primitives::bytecode::eof::types_section::TypesSection". + + (* + pub const fn io_diff(&self) -> i32 { + self.outputs as i32 - self.inputs as i32 + } + *) + Definition io_diff (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.sub + Integer.I32 + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |))) + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |))))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_io_diff : M.IsAssociatedFunction Self "io_diff" io_diff. + + (* + pub fn encode(&self, buffer: &mut Vec) { + buffer.push(self.inputs); + buffer.push(self.outputs); + buffer.extend_from_slice(&self.max_stack_size.to_be_bytes()); + } + *) + Definition encode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; buffer ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let buffer := M.alloc (| buffer |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.read (| buffer |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ + M.read (| buffer |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ], + "extend_from_slice", + [] + |), + [ + M.read (| buffer |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "u16", "to_be_bytes", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |) + |) + ] + |) + |)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_encode : M.IsAssociatedFunction Self "encode" encode. + + (* + pub fn decode(input: &[u8]) -> Result<(Self, &[u8]), EofDecodeError> { + let (input, inputs) = consume_u8(input)?; + let (input, outputs) = consume_u8(input)?; + let (input, max_stack_size) = consume_u16(input)?; + let section = Self { + inputs, + outputs, + max_stack_size, + }; + section.validate()?; + Ok((section, input)) + } + *) + Definition decode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ input ] => + ltac:(M.monadic + (let input := M.alloc (| input |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]; + Ty.path "u8" + ]; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u8", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let input := M.copy (| ฮณ0_0 |) in + let inputs := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]; + Ty.path "u8" + ]; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u8", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let input := M.copy (| ฮณ0_0 |) in + let outputs := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ]; + Ty.path "u16" + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "revm_primitives::bytecode::eof::decode_helpers::consume_u16", + [] + |), + [ M.read (| input |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let input := M.copy (| ฮณ0_0 |) in + let max_stack_size := M.copy (| ฮณ0_1 |) in + let~ section := + M.alloc (| + Value.StructRecord + "revm_primitives::bytecode::eof::types_section::TypesSection" + [ + ("inputs", M.read (| inputs |)); + ("outputs", M.read (| outputs |)); + ("max_stack_size", M.read (| max_stack_size |)) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection", + "validate", + [] + |), + [ section ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path + "revm_primitives::bytecode::eof::types_section::TypesSection"; + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "slice") + [ Ty.path "u8" ] + ] + ]; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::bytecode::eof::EofDecodeError" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ M.read (| section |); M.read (| input |) ] + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_decode : M.IsAssociatedFunction Self "decode" decode. + + (* + pub fn validate(&self) -> Result<(), EofDecodeError> { + if self.inputs > 0x7f || self.outputs > 0x80 || self.max_stack_size > 0x03FF { + return Err(EofDecodeError::InvalidTypesSection); + } + if self.inputs as u16 > self.max_stack_size { + return Err(EofDecodeError::InvalidTypesSection); + } + Ok(()) + } + *) + Definition validate (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + BinOp.Pure.gt + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |)) + (Value.Integer 127), + ltac:(M.monadic + (BinOp.Pure.gt + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "outputs" + |) + |)) + (Value.Integer 128))) + |), + ltac:(M.monadic + (BinOp.Pure.gt + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |) + |)) + (Value.Integer 1023))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidTypesSection" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "inputs" + |) + |))) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::eof::types_section::TypesSection", + "max_stack_size" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::bytecode::eof::EofDecodeError::InvalidTypesSection" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_validate : M.IsAssociatedFunction Self "validate" validate. + End Impl_revm_primitives_bytecode_eof_types_section_TypesSection. + End types_section. + End eof. +End bytecode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/legacy.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/legacy.md new file mode 100644 index 00000000..56a43c97 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/legacy.md @@ -0,0 +1,732 @@ +# ๐Ÿ“ legacy.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/bytecode/legacy.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module bytecode. + Module legacy. + (* StructRecord + { + name := "LegacyAnalyzedBytecode"; + ty_params := []; + fields := + [ + ("bytecode", Ty.path "alloy_primitives::bytes_::Bytes"); + ("original_len", Ty.path "usize"); + ("jump_table", Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode" + [ + ("bytecode", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "bytecode" + |) + ] + |)); + ("original_len", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "usize", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_len" + |) + ] + |)); + ("jump_table", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "jump_table" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + + Module Impl_core_fmt_Debug_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "LegacyAnalyzedBytecode" |); + M.read (| Value.String "bytecode" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "bytecode" + |)); + M.read (| Value.String "original_len" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_len" + |)); + M.read (| Value.String "jump_table" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "jump_table" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "bytecode" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "bytecode" + |) + ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_len" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_len" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable", + [ Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "jump_table" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "jump_table" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + + Module Impl_core_cmp_Eq_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + + Module Impl_core_hash_Hash_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "bytecode" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "usize", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_len" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "jump_table" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + + Module Impl_core_default_Default_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode". + + (* + fn default() -> Self { + Self { + bytecode: Bytes::from_static(&[0]), + original_len: 0, + jump_table: JumpTable(Arc::new(bitvec![u8, Lsb0; 0])), + } + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode" + [ + ("bytecode", + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "from_static", + [] + |), + [ + (* Unsize *) + M.pointer_coercion (M.alloc (| Value.Array [ Value.Integer 0 ] |)) + ] + |)); + ("original_len", Value.Integer 0); + ("jump_table", + Value.StructTuple + "revm_primitives::bytecode::legacy::jump_map::JumpTable" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ], + "from_bitslice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply + (Ty.path "bitvec::array::BitArray") + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "bitvec::order::Lsb0" + ], + [ + Ty.apply + (Ty.path "core::ops::range::RangeTo") + [ Ty.path "usize" ] + ], + "index", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "bitvec::array::BitArray") + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "bitvec::order::Lsb0" + ], + "new", + [] + |), + [ + Value.Array + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "bitvec::mem::BitElement") + [ Ty.path "u8" ], + "new", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::bytecode::legacy::default::ELEM" + |) + |) + ] + |) + |), + "bitvec::mem::BitElement", + "elem" + |) + |) + ] + ] + |) + |); + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.read (| + M.get_constant (| + "revm_primitives::bytecode::legacy::default::BITS" + |) + |)) + ] + ] + |) + ] + |) + ] + |) + ]) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + + Module Impl_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode". + + (* + pub fn new(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self { + Self { + bytecode, + original_len, + jump_table, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ bytecode; original_len; jump_table ] => + ltac:(M.monadic + (let bytecode := M.alloc (| bytecode |) in + let original_len := M.alloc (| original_len |) in + let jump_table := M.alloc (| jump_table |) in + Value.StructRecord + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode" + [ + ("bytecode", M.read (| bytecode |)); + ("original_len", M.read (| original_len |)); + ("jump_table", M.read (| jump_table |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn bytecode(&self) -> &Bytes { + &self.bytecode + } + *) + Definition bytecode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "bytecode" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_bytecode : M.IsAssociatedFunction Self "bytecode" bytecode. + + (* + pub fn original_len(&self) -> usize { + self.original_len + } + *) + Definition original_len (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_len" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_original_len : + M.IsAssociatedFunction Self "original_len" original_len. + + (* + pub fn original_bytes(&self) -> Bytes { + self.bytecode.slice(..self.original_len) + } + *) + Definition original_bytes (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "slice", + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "bytecode" + |); + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_len" + |) + |)) + ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_original_bytes : + M.IsAssociatedFunction Self "original_bytes" original_bytes. + + (* + pub fn original_byte_slice(&self) -> &[u8] { + &self.bytecode[..self.original_len] + } + *) + Definition original_byte_slice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + [ Ty.apply (Ty.path "core::ops::range::RangeTo") [ Ty.path "usize" ] ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "bytecode" + |) + ] + |) + ] + |); + Value.StructRecord + "core::ops::range::RangeTo" + [ + ("end_", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "original_len" + |) + |)) + ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_original_byte_slice : + M.IsAssociatedFunction Self "original_byte_slice" original_byte_slice. + + (* + pub fn jump_table(&self) -> &JumpTable { + &self.jump_table + } + *) + Definition jump_table (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::LegacyAnalyzedBytecode", + "jump_table" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_jump_table : M.IsAssociatedFunction Self "jump_table" jump_table. + End Impl_revm_primitives_bytecode_legacy_LegacyAnalyzedBytecode. + End legacy. +End bytecode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/legacy/jump_map.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/legacy/jump_map.md new file mode 100644 index 00000000..352e6cc1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/bytecode/legacy/jump_map.md @@ -0,0 +1,568 @@ +# ๐Ÿ“ jump_map.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/bytecode/legacy/jump_map.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module bytecode. + Module legacy. + Module jump_map. + (* StructTuple + { + name := "JumpTable"; + ty_params := []; + fields := + [ + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ] + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructTuple + "revm_primitives::bytecode::legacy::jump_map::JumpTable" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::jump_map::JumpTable", + 0 + |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + + Module Impl_core_default_Default_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::bytecode::legacy::jump_map::JumpTable" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::jump_map::JumpTable", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_primitives::bytecode::legacy::jump_map::JumpTable", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + + Module Impl_core_cmp_Eq_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + + Module Impl_core_hash_Hash_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::jump_map::JumpTable", + 0 + |); + M.read (| state |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + + Module Impl_core_fmt_Debug_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable". + + (* + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("JumpTable") + .field("map", &hex::encode(self.0.as_raw_slice())) + .finish() + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "finish", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct", + [] + |), + [ M.read (| f |); M.read (| Value.String "JumpTable" |) ] + |) + |); + M.read (| Value.String "map" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_function (| + "const_hex::encode", + [ + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ], + "as_raw_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::jump_map::JumpTable", + 0 + |) + ] + |) + ] + |) + ] + |) + |)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_bytecode_legacy_jump_map_JumpTable. + + Module Impl_revm_primitives_bytecode_legacy_jump_map_JumpTable. + Definition Self : Ty.t := Ty.path "revm_primitives::bytecode::legacy::jump_map::JumpTable". + + (* + pub fn as_slice(&self) -> &[u8] { + self.0.as_raw_slice() + } + *) + Definition as_slice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ], + "as_raw_slice", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::jump_map::JumpTable", + 0 + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_as_slice : M.IsAssociatedFunction Self "as_slice" as_slice. + + (* + pub fn from_slice(slice: &[u8]) -> Self { + Self(Arc::new(BitVec::from_slice(slice))) + } + *) + Definition from_slice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ slice ] => + ltac:(M.monadic + (let slice := M.alloc (| slice |) in + Value.StructTuple + "revm_primitives::bytecode::legacy::jump_map::JumpTable" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ], + "from_slice", + [] + |), + [ M.read (| slice |) ] + |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_from_slice : M.IsAssociatedFunction Self "from_slice" from_slice. + + (* + pub fn is_valid(&self, pc: usize) -> bool { + pc < self.0.len() && self.0[pc] + } + *) + Definition is_valid (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; pc ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let pc := M.alloc (| pc |) in + LogicalOp.and (| + BinOp.Pure.lt + (M.read (| pc |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ], + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::jump_map::JumpTable", + 0 + |) + ] + |) + ] + |)), + ltac:(M.monadic + (M.read (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ], + [ Ty.path "usize" ], + "index", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.apply + (Ty.path "bitvec::vec::BitVec") + [ Ty.path "u8"; Ty.path "bitvec::order::Lsb0" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::bytecode::legacy::jump_map::JumpTable", + 0 + |) + ] + |); + M.read (| pc |) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_valid : M.IsAssociatedFunction Self "is_valid" is_valid. + End Impl_revm_primitives_bytecode_legacy_jump_map_JumpTable. + End jump_map. + End legacy. +End bytecode. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/constants.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/constants.md new file mode 100644 index 00000000..a33a394f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/constants.md @@ -0,0 +1,136 @@ +# ๐Ÿ“ constants.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/constants.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module constants. + Definition value_MAX_CODE_SIZE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 24576 |))). + + Definition value_BLOCK_HASH_HISTORY : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 256 |))). + + Definition value_BLOCKHASH_SERVE_WINDOW : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 8192 |))). + + Definition value_BLOCKHASH_STORAGE_ADDRESS : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "new", + [] + |), + [ + M.read (| + M.get_constant (| "revm_primitives::constants::BLOCKHASH_STORAGE_ADDRESS::RES" |) + |) + ] + |) + |))). + + Definition value_MAX_INITCODE_SIZE : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + BinOp.Wrap.mul + Integer.Usize + (Value.Integer 2) + (M.read (| M.get_constant (| "revm_primitives::constants::MAX_CODE_SIZE" |) |)) + |))). + + Definition value_PRECOMPILE3 : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "new", + [] + |), + [ + Value.Array + [ + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 0; + Value.Integer 3 + ] + ] + |) + |))). + + Definition value_GAS_PER_BLOB : Value.t := + M.run ltac:(M.monadic (M.alloc (| BinOp.Wrap.shl (Value.Integer 1) (Value.Integer 17) |))). + + Definition value_TARGET_BLOB_NUMBER_PER_BLOCK : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 3 |))). + + Definition value_MAX_BLOB_NUMBER_PER_BLOCK : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + BinOp.Wrap.mul + Integer.U64 + (Value.Integer 2) + (M.read (| + M.get_constant (| "revm_primitives::constants::TARGET_BLOB_NUMBER_PER_BLOCK" |) + |)) + |))). + + Definition value_MAX_BLOB_GAS_PER_BLOCK : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + BinOp.Wrap.mul + Integer.U64 + (M.read (| + M.get_constant (| "revm_primitives::constants::MAX_BLOB_NUMBER_PER_BLOCK" |) + |)) + (M.read (| M.get_constant (| "revm_primitives::constants::GAS_PER_BLOB" |) |)) + |))). + + Definition value_TARGET_BLOB_GAS_PER_BLOCK : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + BinOp.Wrap.mul + Integer.U64 + (M.read (| + M.get_constant (| "revm_primitives::constants::TARGET_BLOB_NUMBER_PER_BLOCK" |) + |)) + (M.read (| M.get_constant (| "revm_primitives::constants::GAS_PER_BLOB" |) |)) + |))). + + Definition value_MIN_BLOB_GASPRICE : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 1 |))). + + Definition value_BLOB_GASPRICE_UPDATE_FRACTION : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 3338477 |))). + + Definition value_VERSIONED_HASH_VERSION_KZG : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 1 |))). +End constants. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db.md new file mode 100644 index 00000000..e9f9e397 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db.md @@ -0,0 +1,1565 @@ +# ๐Ÿ“ db.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/db.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + (* Trait *) + (* Empty module 'Database' *) + + Module underscore. + Module Impl_revm_primitives_db_Database_where_revm_primitives_db_Database_T_where_core_marker_Sized_T_for_ref_mut_T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&mut") [ T ]. + + (* #[auto_impl(&mut, Box)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&mut, Box)] *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::Database", T, [], "basic", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::Database", T, [], "code_by_hash", [] |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::Database", T, [], "storage", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::Database", T, [], "block_hash", [] |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::Database" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_Database_where_revm_primitives_db_Database_T_where_core_marker_Sized_T_for_ref_mut_T. + Module Impl_revm_primitives_db_Database_where_revm_primitives_db_Database_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::boxed::Box") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&mut, Box)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&mut, Box)] *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::Database", T, [], "basic", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::Database", T, [], "code_by_hash", [] |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::Database", T, [], "storage", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::Database", T, [], "block_hash", [] |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::Database" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_Database_where_revm_primitives_db_Database_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_DatabaseCommit_T_where_core_marker_Sized_T_for_ref_mut_T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&mut") [ T ]. + + (* #[auto_impl(&mut, Box)] *) + Definition commit (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; changes ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let changes := M.alloc (| changes |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseCommit", T, [], "commit", [] |), + [ M.read (| M.read (| self |) |); M.read (| changes |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseCommit" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("commit", InstanceField.Method (commit T)) ]. + End Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_DatabaseCommit_T_where_core_marker_Sized_T_for_ref_mut_T. + Module Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_DatabaseCommit_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::boxed::Box") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&mut, Box)] *) + Definition commit (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; changes ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let changes := M.alloc (| changes |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseCommit", T, [], "commit", [] |), + [ M.read (| M.read (| self |) |); M.read (| changes |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseCommit" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("commit", InstanceField.Method (commit T)) ]. + End Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_DatabaseCommit_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_ref__T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&") [ T ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "basic_ref", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "code_by_hash_ref", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "storage_ref", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "block_hash_ref", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic_ref", InstanceField.Method (basic_ref T)); + ("code_by_hash_ref", InstanceField.Method (code_by_hash_ref T)); + ("storage_ref", InstanceField.Method (storage_ref T)); + ("block_hash_ref", InstanceField.Method (block_hash_ref T)) + ]. + End Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_ref__T. + Module Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_ref_mut_T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&mut") [ T ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "basic_ref", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "code_by_hash_ref", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "storage_ref", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "block_hash_ref", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic_ref", InstanceField.Method (basic_ref T)); + ("code_by_hash_ref", InstanceField.Method (code_by_hash_ref T)); + ("storage_ref", InstanceField.Method (storage_ref T)); + ("block_hash_ref", InstanceField.Method (block_hash_ref T)) + ]. + End Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_ref_mut_T. + Module Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::boxed::Box") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "basic_ref", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "code_by_hash_ref", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "storage_ref", [] |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "block_hash_ref", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic_ref", InstanceField.Method (basic_ref T)); + ("code_by_hash_ref", InstanceField.Method (code_by_hash_ref T)); + ("storage_ref", InstanceField.Method (storage_ref T)); + ("block_hash_ref", InstanceField.Method (block_hash_ref T)) + ]. + End Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_alloc_rc_Rc_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "basic_ref", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "code_by_hash_ref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| code_hash |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "storage_ref", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| address |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "block_hash_ref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| number |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic_ref", InstanceField.Method (basic_ref T)); + ("code_by_hash_ref", InstanceField.Method (code_by_hash_ref T)); + ("storage_ref", InstanceField.Method (storage_ref T)); + ("block_hash_ref", InstanceField.Method (block_hash_ref T)) + ]. + End Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_alloc_rc_Rc_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "basic_ref", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "code_by_hash_ref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| code_hash |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "storage_ref", [] |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| address |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash_ref (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "block_hash_ref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| number |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic_ref", InstanceField.Method (basic_ref T)); + ("code_by_hash_ref", InstanceField.Method (code_by_hash_ref T)); + ("storage_ref", InstanceField.Method (storage_ref T)); + ("block_hash_ref", InstanceField.Method (block_hash_ref T)) + ]. + End Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_T_where_core_marker_Sized_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + End underscore. + + + (* Trait *) + (* Empty module 'DatabaseCommit' *) + + + + (* Trait *) + (* Empty module 'DatabaseRef' *) + + + + + + + (* StructTuple + { + name := "WrapDatabaseRef"; + ty_params := [ "T" ]; + fields := [ T ]; + } *) + + Module Impl_core_clone_Clone_where_core_clone_Clone_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* Clone *) + Definition clone (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructTuple + "revm_primitives::db::WrapDatabaseRef" + [ + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", T, [], "clone", [] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone T)) ]. + End Impl_core_clone_Clone_where_core_clone_Clone_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_marker_Copy_where_core_marker_Copy_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::marker::Copy" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_where_core_marker_Copy_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_fmt_Debug_where_core_fmt_Debug_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* Debug *) + Definition fmt (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "WrapDatabaseRef" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt T)) ]. + End Impl_core_fmt_Debug_where_core_fmt_Debug_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_default_Default_where_core_default_Default_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* Default *) + Definition default (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::db::WrapDatabaseRef" + [ + M.call_closure (| + M.get_trait_method (| "core::default::Default", T, [], "default", [] |), + [] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::default::Default" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method (default T)) ]. + End Impl_core_default_Default_where_core_default_Default_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_marker_StructuralPartialEq_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::marker::StructuralPartialEq" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_cmp_PartialEq_where_core_cmp_PartialEq_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* PartialEq *) + Definition eq (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| "core::cmp::PartialEq", T, [ T ], "eq", [] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::cmp::PartialEq" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method (eq T)) ]. + End Impl_core_cmp_PartialEq_where_core_cmp_PartialEq_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_marker_StructuralEq_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::marker::StructuralEq" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_cmp_Eq_where_core_cmp_Eq_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* Eq *) + Definition assert_receiver_is_total_eq (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::cmp::Eq" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method (assert_receiver_is_total_eq T)) ]. + End Impl_core_cmp_Eq_where_core_cmp_Eq_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_cmp_PartialOrd_where_core_cmp_PartialOrd_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* PartialOrd *) + Definition partial_cmp (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| "core::cmp::PartialOrd", T, [ T ], "partial_cmp", [] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::cmp::PartialOrd" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method (partial_cmp T)) ]. + End Impl_core_cmp_PartialOrd_where_core_cmp_PartialOrd_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_cmp_Ord_where_core_cmp_Ord_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* Ord *) + Definition cmp (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", T, [], "cmp", [] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::cmp::Ord" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method (cmp T)) ]. + End Impl_core_cmp_Ord_where_core_cmp_Ord_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_hash_Hash_where_core_hash_Hash_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* Hash *) + Definition hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", T, [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |); + M.read (| state |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "core::hash::Hash" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method (hash T)) ]. + End Impl_core_hash_Hash_where_core_hash_Hash_T_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_core_convert_From_where_revm_primitives_db_DatabaseRef_F_F_for_revm_primitives_db_WrapDatabaseRef_F. + Definition Self (F : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ F ]. + + (* + fn from(f: F) -> Self { + WrapDatabaseRef(f) + } + *) + Definition from (F : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self F in + match ฯ„, ฮฑ with + | [], [ f ] => + ltac:(M.monadic + (let f := M.alloc (| f |) in + Value.StructTuple "revm_primitives::db::WrapDatabaseRef" [ M.read (| f |) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (F : Ty.t), + M.IsTraitInstance + "core::convert::From" + (Self F) + (* Trait polymorphic types *) [ (* T *) F ] + (* Instance *) [ ("from", InstanceField.Method (from F)) ]. + End Impl_core_convert_From_where_revm_primitives_db_DatabaseRef_F_F_for_revm_primitives_db_WrapDatabaseRef_F. + + (* Trait *) + (* Empty module 'DatabaseWithDebugError' *) + + Module Impl_revm_primitives_db_Database_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* type Error = T::Error; *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.0.basic_ref(address) + } + *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "basic_ref", [] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.0.code_by_hash_ref(code_hash) + } + *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "code_by_hash_ref", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |); + M.read (| code_hash |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn storage(&mut self, address: Address, index: U256) -> Result { + self.0.storage_ref(address, index) + } + *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseRef", T, [], "storage_ref", [] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |); + M.read (| address |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn block_hash(&mut self, number: U256) -> Result { + self.0.block_hash_ref(number) + } + *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + T, + [], + "block_hash_ref", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |); + M.read (| number |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::Database" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_Database_where_revm_primitives_db_DatabaseRef_T_for_revm_primitives_db_WrapDatabaseRef_T. + + Module Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_DatabaseRef_T_where_revm_primitives_db_DatabaseCommit_T_for_revm_primitives_db_WrapDatabaseRef_T. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ T ]. + + (* + fn commit(&mut self, changes: HashMap) { + self.0.commit(changes) + } + *) + Definition commit (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; changes ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let changes := M.alloc (| changes |) in + M.call_closure (| + M.get_trait_method (| "revm_primitives::db::DatabaseCommit", T, [], "commit", [] |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::db::WrapDatabaseRef", + 0 + |); + M.read (| changes |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseCommit" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) [ ("commit", InstanceField.Method (commit T)) ]. + End Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_DatabaseRef_T_where_revm_primitives_db_DatabaseCommit_T_for_revm_primitives_db_WrapDatabaseRef_T. + + (* StructRecord + { + name := "RefDBWrapper"; + ty_params := [ "E" ]; + fields := + [ + ("db", + Ty.apply (Ty.path "&") [ Ty.dyn [ ("revm_primitives::db::DatabaseRef::Trait", []) ] ]) + ]; + } *) + + Module Impl_revm_primitives_db_RefDBWrapper_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::RefDBWrapper") [ E ]. + + (* + pub fn new(db: &'a dyn DatabaseRef) -> Self { + Self { db } + } + *) + Definition new (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ db ] => + ltac:(M.monadic + (let db := M.alloc (| db |) in + Value.StructRecord + "revm_primitives::db::RefDBWrapper" + [ ("db", (* Unsize *) M.pointer_coercion (M.read (| db |))) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : forall (E : Ty.t), M.IsAssociatedFunction (Self E) "new" (new E). + End Impl_revm_primitives_db_RefDBWrapper_E. + + Module Impl_revm_primitives_db_Database_for_revm_primitives_db_RefDBWrapper_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::RefDBWrapper") [ E ]. + + (* type Error = E; *) + Definition _Error (E : Ty.t) : Ty.t := E. + + (* + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.db.basic_ref(address) + } + *) + Definition basic (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + Ty.dyn [ ("revm_primitives::db::DatabaseRef::Trait", []) ], + [], + "basic_ref", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::RefDBWrapper", + "db" + |) + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.db.code_by_hash_ref(code_hash) + } + *) + Definition code_by_hash (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + Ty.dyn [ ("revm_primitives::db::DatabaseRef::Trait", []) ], + [], + "code_by_hash_ref", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::RefDBWrapper", + "db" + |) + |); + M.read (| code_hash |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn storage(&mut self, address: Address, index: U256) -> Result { + self.db.storage_ref(address, index) + } + *) + Definition storage (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + Ty.dyn [ ("revm_primitives::db::DatabaseRef::Trait", []) ], + [], + "storage_ref", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::RefDBWrapper", + "db" + |) + |); + M.read (| address |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn block_hash(&mut self, number: U256) -> Result { + self.db.block_hash_ref(number) + } + *) + Definition block_hash (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + Ty.dyn [ ("revm_primitives::db::DatabaseRef::Trait", []) ], + [], + "block_hash_ref", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::RefDBWrapper", + "db" + |) + |); + M.read (| number |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (E : Ty.t), + M.IsTraitInstance + "revm_primitives::db::Database" + (Self E) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error E)); + ("basic", InstanceField.Method (basic E)); + ("code_by_hash", InstanceField.Method (code_by_hash E)); + ("storage", InstanceField.Method (storage E)); + ("block_hash", InstanceField.Method (block_hash E)) + ]. + End Impl_revm_primitives_db_Database_for_revm_primitives_db_RefDBWrapper_E. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components.md new file mode 100644 index 00000000..b562dd4a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components.md @@ -0,0 +1,728 @@ +# ๐Ÿ“ components.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/db/components.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module components. + (* StructRecord + { + name := "DatabaseComponents"; + ty_params := [ "S"; "BH" ]; + fields := [ ("state", S); ("block_hash", BH) ]; + } *) + + Module Impl_core_fmt_Debug_where_core_fmt_Debug_S_where_core_fmt_Debug_BH_for_revm_primitives_db_components_DatabaseComponents_S_BH. + Definition Self (S BH : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::components::DatabaseComponents") [ S; BH ]. + + (* Debug *) + Definition fmt (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "DatabaseComponents" |); + M.read (| Value.String "state" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "state" + |)); + M.read (| Value.String "block_hash" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "block_hash" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (S BH : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self S BH) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt S BH)) ]. + End Impl_core_fmt_Debug_where_core_fmt_Debug_S_where_core_fmt_Debug_BH_for_revm_primitives_db_components_DatabaseComponents_S_BH. + + (* + Enum DatabaseComponentError + { + ty_params := [ "SE"; "BHE" ]; + variants := + [ + { + name := "State"; + item := StructTuple [ SE ]; + discriminant := None; + }; + { + name := "BlockHash"; + item := StructTuple [ BHE ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_where_core_fmt_Debug_SE_where_core_fmt_Debug_BHE_for_revm_primitives_db_components_DatabaseComponentError_SE_BHE. + Definition Self (SE BHE : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::components::DatabaseComponentError") [ SE; BHE ]. + + (* Debug *) + Definition fmt (SE BHE : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self SE BHE in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::db::components::DatabaseComponentError::State", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "State" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::db::components::DatabaseComponentError::BlockHash", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "BlockHash" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (SE BHE : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self SE BHE) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt SE BHE)) ]. + End Impl_core_fmt_Debug_where_core_fmt_Debug_SE_where_core_fmt_Debug_BHE_for_revm_primitives_db_components_DatabaseComponentError_SE_BHE. + + Module Impl_revm_primitives_db_Database_where_revm_primitives_db_components_state_State_S_where_revm_primitives_db_components_block_hash_BlockHash_BH_for_revm_primitives_db_components_DatabaseComponents_S_BH. + Definition Self (S BH : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::components::DatabaseComponents") [ S; BH ]. + + (* type Error = DatabaseComponentError; *) + Definition _Error (S BH : Ty.t) : Ty.t := + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]. + + (* + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.state.basic(address).map_err(Self::Error::State) + } + *) + Definition basic (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]; + Ty.associated + ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::State", + S, + [], + "basic", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "state" + |); + M.read (| address |) + ] + |); + M.constructor_as_closure + "revm_primitives::db::components::DatabaseComponentError::State" + ] + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.state + .code_by_hash(code_hash) + .map_err(Self::Error::State) + } + *) + Definition code_by_hash (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "revm_primitives::bytecode::Bytecode"; Ty.associated ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::State", + S, + [], + "code_by_hash", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "state" + |); + M.read (| code_hash |) + ] + |); + M.constructor_as_closure + "revm_primitives::db::components::DatabaseComponentError::State" + ] + |))) + | _, _ => M.impossible + end. + + (* + fn storage(&mut self, address: Address, index: U256) -> Result { + self.state + .storage(address, index) + .map_err(Self::Error::State) + } + *) + Definition storage (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::result::Result") [ Ty.path "ruint::Uint"; Ty.associated ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::State", + S, + [], + "storage", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "state" + |); + M.read (| address |); + M.read (| index |) + ] + |); + M.constructor_as_closure + "revm_primitives::db::components::DatabaseComponentError::State" + ] + |))) + | _, _ => M.impossible + end. + + (* + fn block_hash(&mut self, number: U256) -> Result { + self.block_hash + .block_hash(number) + .map_err(Self::Error::BlockHash) + } + *) + Definition block_hash (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes"; Ty.associated ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHash", + BH, + [], + "block_hash", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "block_hash" + |); + M.read (| number |) + ] + |); + M.constructor_as_closure + "revm_primitives::db::components::DatabaseComponentError::BlockHash" + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (S BH : Ty.t), + M.IsTraitInstance + "revm_primitives::db::Database" + (Self S BH) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error S BH)); + ("basic", InstanceField.Method (basic S BH)); + ("code_by_hash", InstanceField.Method (code_by_hash S BH)); + ("storage", InstanceField.Method (storage S BH)); + ("block_hash", InstanceField.Method (block_hash S BH)) + ]. + End Impl_revm_primitives_db_Database_where_revm_primitives_db_components_state_State_S_where_revm_primitives_db_components_block_hash_BlockHash_BH_for_revm_primitives_db_components_DatabaseComponents_S_BH. + + Module Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_components_state_StateRef_S_where_revm_primitives_db_components_block_hash_BlockHashRef_BH_for_revm_primitives_db_components_DatabaseComponents_S_BH. + Definition Self (S BH : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::components::DatabaseComponents") [ S; BH ]. + + (* type Error = DatabaseComponentError; *) + Definition _Error (S BH : Ty.t) : Ty.t := + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]. + + (* + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + self.state.basic(address).map_err(Self::Error::State) + } + *) + Definition basic_ref (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]; + Ty.associated + ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + S, + [], + "basic", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "state" + |); + M.read (| address |) + ] + |); + M.constructor_as_closure + "revm_primitives::db::components::DatabaseComponentError::State" + ] + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + self.state + .code_by_hash(code_hash) + .map_err(Self::Error::State) + } + *) + Definition code_by_hash_ref (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "revm_primitives::bytecode::Bytecode"; Ty.associated ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + S, + [], + "code_by_hash", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "state" + |); + M.read (| code_hash |) + ] + |); + M.constructor_as_closure + "revm_primitives::db::components::DatabaseComponentError::State" + ] + |))) + | _, _ => M.impossible + end. + + (* + fn storage_ref(&self, address: Address, index: U256) -> Result { + self.state + .storage(address, index) + .map_err(Self::Error::State) + } + *) + Definition storage_ref (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::result::Result") [ Ty.path "ruint::Uint"; Ty.associated ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + S, + [], + "storage", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "state" + |); + M.read (| address |); + M.read (| index |) + ] + |); + M.constructor_as_closure + "revm_primitives::db::components::DatabaseComponentError::State" + ] + |))) + | _, _ => M.impossible + end. + + (* + fn block_hash_ref(&self, number: U256) -> Result { + self.block_hash + .block_hash(number) + .map_err(Self::Error::BlockHash) + } + *) + Definition block_hash_ref (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes"; Ty.associated ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path "revm_primitives::db::components::DatabaseComponentError") + [ Ty.associated; Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHashRef", + BH, + [], + "block_hash", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "block_hash" + |); + M.read (| number |) + ] + |); + M.constructor_as_closure + "revm_primitives::db::components::DatabaseComponentError::BlockHash" + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (S BH : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseRef" + (Self S BH) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error S BH)); + ("basic_ref", InstanceField.Method (basic_ref S BH)); + ("code_by_hash_ref", InstanceField.Method (code_by_hash_ref S BH)); + ("storage_ref", InstanceField.Method (storage_ref S BH)); + ("block_hash_ref", InstanceField.Method (block_hash_ref S BH)) + ]. + End Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_components_state_StateRef_S_where_revm_primitives_db_components_block_hash_BlockHashRef_BH_for_revm_primitives_db_components_DatabaseComponents_S_BH. + + Module Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_DatabaseCommit_S_where_revm_primitives_db_components_block_hash_BlockHashRef_BH_for_revm_primitives_db_components_DatabaseComponents_S_BH. + Definition Self (S BH : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::db::components::DatabaseComponents") [ S; BH ]. + + (* + fn commit(&mut self, changes: HashMap) { + self.state.commit(changes); + } + *) + Definition commit (S BH : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self S BH in + match ฯ„, ฮฑ with + | [], [ self; changes ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let changes := M.alloc (| changes |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseCommit", + S, + [], + "commit", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::db::components::DatabaseComponents", + "state" + |); + M.read (| changes |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (S BH : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseCommit" + (Self S BH) + (* Trait polymorphic types *) [] + (* Instance *) [ ("commit", InstanceField.Method (commit S BH)) ]. + End Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_DatabaseCommit_S_where_revm_primitives_db_components_block_hash_BlockHashRef_BH_for_revm_primitives_db_components_DatabaseComponents_S_BH. + End components. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components/block_hash.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components/block_hash.md new file mode 100644 index 00000000..aba0276d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components/block_hash.md @@ -0,0 +1,437 @@ +# ๐Ÿ“ block_hash.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/db/components/block_hash.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module components. + Module block_hash. + (* Trait *) + (* Empty module 'BlockHash' *) + + Module underscore. + Module Impl_revm_primitives_db_components_block_hash_BlockHash_where_revm_primitives_db_components_block_hash_BlockHash_T_where_core_marker_Sized_T_for_ref_mut_T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&mut") [ T ]. + + (* #[auto_impl(&mut, Box)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&mut, Box)] *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHash", + T, + [], + "block_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::block_hash::BlockHash" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_components_block_hash_BlockHash_where_revm_primitives_db_components_block_hash_BlockHash_T_where_core_marker_Sized_T_for_ref_mut_T. + Module Impl_revm_primitives_db_components_block_hash_BlockHash_where_revm_primitives_db_components_block_hash_BlockHash_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::boxed::Box") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&mut, Box)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&mut, Box)] *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHash", + T, + [], + "block_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::block_hash::BlockHash" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_components_block_hash_BlockHash_where_revm_primitives_db_components_block_hash_BlockHash_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_ref__T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&") [ T ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHashRef", + T, + [], + "block_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::block_hash::BlockHashRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_ref__T. + Module Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_ref_mut_T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&mut") [ T ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHashRef", + T, + [], + "block_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::block_hash::BlockHashRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_ref_mut_T. + Module Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::boxed::Box") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHashRef", + T, + [], + "block_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::block_hash::BlockHashRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_alloc_rc_Rc_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHashRef", + T, + [], + "block_hash", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| number |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::block_hash::BlockHashRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_alloc_rc_Rc_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHashRef", + T, + [], + "block_hash", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| number |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::block_hash::BlockHashRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_components_block_hash_BlockHashRef_where_revm_primitives_db_components_block_hash_BlockHashRef_T_where_core_marker_Sized_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + End underscore. + + + (* Trait *) + (* Empty module 'BlockHashRef' *) + + + + + + + Module Impl_revm_primitives_db_components_block_hash_BlockHash_where_revm_primitives_db_components_block_hash_BlockHashRef_T_for_ref__T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&") [ T ]. + + (* type Error = ::Error; *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* + fn block_hash(&mut self, number: U256) -> Result { + BlockHashRef::block_hash( *self, number) + } + *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHashRef", + T, + [], + "block_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::block_hash::BlockHash" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_components_block_hash_BlockHash_where_revm_primitives_db_components_block_hash_BlockHashRef_T_for_ref__T. + + Module Impl_revm_primitives_db_components_block_hash_BlockHash_where_revm_primitives_db_components_block_hash_BlockHashRef_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ]. + + (* type Error = ::Error; *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* + fn block_hash(&mut self, number: U256) -> Result { + self.deref().block_hash(number) + } + *) + Definition block_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::block_hash::BlockHashRef", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "block_hash", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::sync::Arc") + [ T; Ty.path "alloc::alloc::Global" ] + ], + [], + "deref", + [] + |), + [ self ] + |); + M.read (| number |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::block_hash::BlockHash" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("block_hash", InstanceField.Method (block_hash T)) + ]. + End Impl_revm_primitives_db_components_block_hash_BlockHash_where_revm_primitives_db_components_block_hash_BlockHashRef_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + End block_hash. + End components. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components/state.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components/state.md new file mode 100644 index 00000000..ccee9ff8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/db/components/state.md @@ -0,0 +1,945 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/db/components/state.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module components. + Module state. + (* Trait *) + (* Empty module 'State' *) + + Module underscore. + Module Impl_revm_primitives_db_components_state_State_where_revm_primitives_db_components_state_State_T_where_core_marker_Sized_T_for_ref_mut_T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&mut") [ T ]. + + (* #[auto_impl(&mut, Box)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&mut, Box)] *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::State", + T, + [], + "basic", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::State", + T, + [], + "code_by_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::State", + T, + [], + "storage", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::state::State" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)) + ]. + End Impl_revm_primitives_db_components_state_State_where_revm_primitives_db_components_state_State_T_where_core_marker_Sized_T_for_ref_mut_T. + Module Impl_revm_primitives_db_components_state_State_where_revm_primitives_db_components_state_State_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::boxed::Box") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&mut, Box)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&mut, Box)] *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::State", + T, + [], + "basic", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::State", + T, + [], + "code_by_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::State", + T, + [], + "storage", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::state::State" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)) + ]. + End Impl_revm_primitives_db_components_state_State_where_revm_primitives_db_components_state_State_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_ref__T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&") [ T ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "basic", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "code_by_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "storage", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::state::StateRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)) + ]. + End Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_ref__T. + Module Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_ref_mut_T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&mut") [ T ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "basic", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "code_by_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "storage", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::state::StateRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)) + ]. + End Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_ref_mut_T. + Module Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::boxed::Box") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "basic", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "code_by_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "storage", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::state::StateRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)) + ]. + End Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_alloc_boxed_Box_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_alloc_rc_Rc_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "basic", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "code_by_hash", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| code_hash |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "storage", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::rc::Rc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| address |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::state::StateRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)) + ]. + End Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_alloc_rc_Rc_T_alloc_alloc_Global. + Module Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "basic", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "code_by_hash", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| code_hash |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&, &mut, Box, Rc, Arc)] *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "storage", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |); + M.read (| address |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::state::StateRef" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)) + ]. + End Impl_revm_primitives_db_components_state_StateRef_where_revm_primitives_db_components_state_StateRef_T_where_core_marker_Sized_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + End underscore. + + + (* Trait *) + (* Empty module 'StateRef' *) + + + + + + + Module Impl_revm_primitives_db_components_state_State_where_revm_primitives_db_components_state_StateRef_T_for_ref__T. + Definition Self (T : Ty.t) : Ty.t := Ty.apply (Ty.path "&") [ T ]. + + (* type Error = ::Error; *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* + fn basic(&mut self, address: Address) -> Result, Self::Error> { + StateRef::basic( *self, address) + } + *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "basic", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash(&mut self, code_hash: B256) -> Result { + StateRef::code_by_hash( *self, code_hash) + } + *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "code_by_hash", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* + fn storage(&mut self, address: Address, index: U256) -> Result { + StateRef::storage( *self, address, index) + } + *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + T, + [], + "storage", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::state::State" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)) + ]. + End Impl_revm_primitives_db_components_state_State_where_revm_primitives_db_components_state_StateRef_T_for_ref__T. + + Module Impl_revm_primitives_db_components_state_State_where_revm_primitives_db_components_state_StateRef_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + Definition Self (T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ]. + + (* type Error = ::Error; *) + Definition _Error (T : Ty.t) : Ty.t := Ty.associated. + + (* + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.deref().basic(address) + } + *) + Definition basic (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "basic", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::sync::Arc") + [ T; Ty.path "alloc::alloc::Global" ] + ], + [], + "deref", + [] + |), + [ self ] + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.deref().code_by_hash(code_hash) + } + *) + Definition code_by_hash (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "code_by_hash", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::sync::Arc") + [ T; Ty.path "alloc::alloc::Global" ] + ], + [], + "deref", + [] + |), + [ self ] + |); + M.read (| code_hash |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn storage(&mut self, address: Address, index: U256) -> Result { + self.deref().storage(address, index) + } + *) + Definition storage (T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self T in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::components::state::StateRef", + Ty.apply (Ty.path "alloc::sync::Arc") [ T; Ty.path "alloc::alloc::Global" ], + [], + "storage", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::sync::Arc") + [ T; Ty.path "alloc::alloc::Global" ] + ], + [], + "deref", + [] + |), + [ self ] + |); + M.read (| address |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (T : Ty.t), + M.IsTraitInstance + "revm_primitives::db::components::state::State" + (Self T) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error T)); + ("basic", InstanceField.Method (basic T)); + ("code_by_hash", InstanceField.Method (code_by_hash T)); + ("storage", InstanceField.Method (storage T)) + ]. + End Impl_revm_primitives_db_components_state_State_where_revm_primitives_db_components_state_StateRef_T_for_alloc_sync_Arc_T_alloc_alloc_Global. + End state. + End components. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/env.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/env.md new file mode 100644 index 00000000..b42dbe66 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/env.md @@ -0,0 +1,7708 @@ +# ๐Ÿ“ env.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/env.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module env. + (* StructRecord + { + name := "Env"; + ty_params := []; + fields := + [ + ("cfg", Ty.path "revm_primitives::env::CfgEnv"); + ("block", Ty.path "revm_primitives::env::BlockEnv"); + ("tx", Ty.path "revm_primitives::env::TxEnv") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_Env. + Definition Self : Ty.t := Ty.path "revm_primitives::env::Env". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::env::Env" + [ + ("cfg", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::CfgEnv", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "cfg" + |) + ] + |)); + ("block", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::BlockEnv", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |) + ] + |)); + ("tx", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::TxEnv", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_Env. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_Env. + Definition Self : Ty.t := Ty.path "revm_primitives::env::Env". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Env" |); + M.read (| Value.String "cfg" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "cfg" + |)); + M.read (| Value.String "block" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |)); + M.read (| Value.String "tx" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_Env. + + Module Impl_core_default_Default_for_revm_primitives_env_Env. + Definition Self : Ty.t := Ty.path "revm_primitives::env::Env". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::env::Env" + [ + ("cfg", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::env::CfgEnv", + [], + "default", + [] + |), + [] + |)); + ("block", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::env::BlockEnv", + [], + "default", + [] + |), + [] + |)); + ("tx", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::env::TxEnv", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_env_Env. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_Env. + Definition Self : Ty.t := Ty.path "revm_primitives::env::Env". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_Env. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_Env. + Definition Self : Ty.t := Ty.path "revm_primitives::env::Env". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::CfgEnv", + [ Ty.path "revm_primitives::env::CfgEnv" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "cfg" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::Env", + "cfg" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::BlockEnv", + [ Ty.path "revm_primitives::env::BlockEnv" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::Env", + "block" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::TxEnv", + [ Ty.path "revm_primitives::env::TxEnv" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::Env", + "tx" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_Env. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_Env. + Definition Self : Ty.t := Ty.path "revm_primitives::env::Env". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_Env. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_Env. + Definition Self : Ty.t := Ty.path "revm_primitives::env::Env". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_Env. + + Module Impl_revm_primitives_env_Env. + Definition Self : Ty.t := Ty.path "revm_primitives::env::Env". + + (* + pub fn clear(&mut self) { + *self = Self::default(); + } + *) + Definition clear (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.write (| + M.read (| self |), + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::env::Env", + [], + "default", + [] + |), + [] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_clear : M.IsAssociatedFunction Self "clear" clear. + + (* + pub fn boxed(cfg: CfgEnv, block: BlockEnv, tx: TxEnv) -> Box { + Box::new(Self { cfg, block, tx }) + } + *) + Definition boxed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ cfg; block; tx ] => + ltac:(M.monadic + (let cfg := M.alloc (| cfg |) in + let block := M.alloc (| block |) in + let tx := M.alloc (| tx |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [ + Value.StructRecord + "revm_primitives::env::Env" + [ ("cfg", M.read (| cfg |)); ("block", M.read (| block |)); ("tx", M.read (| tx |)) + ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_boxed : M.IsAssociatedFunction Self "boxed" boxed. + + (* + pub fn effective_gas_price(&self) -> U256 { + if let Some(priority_fee) = self.tx.gas_priority_fee { + min(self.tx.gas_price, self.block.basefee + priority_fee) + } else { + self.tx.gas_price + } + } + *) + Definition effective_gas_price (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_priority_fee" + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let priority_fee := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_function (| "core::cmp::min", [ Ty.path "ruint::Uint" ] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_price" + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Add", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "add", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "basefee" + |) + |); + M.read (| priority_fee |) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_price" + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_effective_gas_price : + M.IsAssociatedFunction Self "effective_gas_price" effective_gas_price. + + (* + pub fn calc_data_fee(&self) -> Option { + self.block.get_blob_gasprice().map(|blob_gas_price| { + U256::from(blob_gas_price).saturating_mul(U256::from(self.tx.get_total_blob_gas())) + }) + } + *) + Definition calc_data_fee (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "u128" ], + "map", + [ + Ty.path "ruint::Uint"; + Ty.function [ Ty.tuple [ Ty.path "u128" ] ] (Ty.path "ruint::Uint") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::BlockEnv", + "get_blob_gasprice", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let blob_gas_price := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "saturating_mul", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u128" ] + |), + [ M.read (| blob_gas_price |) ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::TxEnv", + "get_total_blob_gas", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |) + ] + |) + ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_calc_data_fee : + M.IsAssociatedFunction Self "calc_data_fee" calc_data_fee. + + (* + pub fn calc_max_data_fee(&self) -> Option { + self.tx.max_fee_per_blob_gas.map(|max_fee_per_blob_gas| { + max_fee_per_blob_gas.saturating_mul(U256::from(self.tx.get_total_blob_gas())) + }) + } + *) + Definition calc_max_data_fee (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "map", + [ + Ty.path "ruint::Uint"; + Ty.function [ Ty.tuple [ Ty.path "ruint::Uint" ] ] (Ty.path "ruint::Uint") + ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "max_fee_per_blob_gas" + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let max_fee_per_blob_gas := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "saturating_mul", + [] + |), + [ + M.read (| max_fee_per_blob_gas |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::TxEnv", + "get_total_blob_gas", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |) + ] + |) + ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_calc_max_data_fee : + M.IsAssociatedFunction Self "calc_max_data_fee" calc_max_data_fee. + + (* + pub fn validate_block_env(&self) -> Result<(), InvalidHeader> { + // `prevrandao` is required for the merge + if SPEC::enabled(SpecId::MERGE) && self.block.prevrandao.is_none() { + return Err(InvalidHeader::PrevrandaoNotSet); + } + // `excess_blob_gas` is required for Cancun + if SPEC::enabled(SpecId::CANCUN) && self.block.blob_excess_gas_and_price.is_none() { + return Err(InvalidHeader::ExcessBlobGasNotSet); + } + Ok(()) + } + *) + Definition validate_block_env (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC ], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::MERGE" + [] + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "is_none", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "prevrandao" + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidHeader::PrevrandaoNotSet" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CANCUN" + [] + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ], + "is_none", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "blob_excess_gas_and_price" + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidHeader::ExcessBlobGasNotSet" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_validate_block_env : + M.IsAssociatedFunction Self "validate_block_env" validate_block_env. + + (* + pub fn validate_tx(&self) -> Result<(), InvalidTransaction> { + // BASEFEE tx check + if SPEC::enabled(SpecId::LONDON) { + if let Some(priority_fee) = self.tx.gas_priority_fee { + if priority_fee > self.tx.gas_price { + // or gas_max_fee for eip1559 + return Err(InvalidTransaction::PriorityFeeGreaterThanMaxFee); + } + } + + // check minimal cost against basefee + if !self.cfg.is_base_fee_check_disabled() + && self.effective_gas_price() < self.block.basefee + { + return Err(InvalidTransaction::GasPriceLessThanBasefee); + } + } + + // Check if gas_limit is more than block_gas_limit + if !self.cfg.is_block_gas_limit_disabled() + && U256::from(self.tx.gas_limit) > self.block.gas_limit + { + return Err(InvalidTransaction::CallerGasLimitMoreThanBlock); + } + + // EIP-3860: Limit and meter initcode + if SPEC::enabled(SpecId::SHANGHAI) && self.tx.transact_to.is_create() { + let max_initcode_size = self + .cfg + .limit_contract_code_size + .map(|limit| limit.saturating_mul(2)) + .unwrap_or(MAX_INITCODE_SIZE); + if self.tx.data.len() > max_initcode_size { + return Err(InvalidTransaction::CreateInitCodeSizeLimit); + } + } + + // Check if the transaction's chain id is correct + if let Some(tx_chain_id) = self.tx.chain_id { + if tx_chain_id != self.cfg.chain_id { + return Err(InvalidTransaction::InvalidChainId); + } + } + + // Check that access list is empty for transactions before BERLIN + if !SPEC::enabled(SpecId::BERLIN) && !self.tx.access_list.is_empty() { + return Err(InvalidTransaction::AccessListNotSupported); + } + + // - For CANCUN and later, check that the gas price is not more than the tx max + // - For before CANCUN, check that `blob_hashes` and `max_fee_per_blob_gas` are empty / not set + if SPEC::enabled(SpecId::CANCUN) { + // Presence of max_fee_per_blob_gas means that this is blob transaction. + if let Some(max) = self.tx.max_fee_per_blob_gas { + // ensure that the user was willing to at least pay the current blob gasprice + let price = self.block.get_blob_gasprice().expect("already checked"); + if U256::from(price) > max { + return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); + } + + // there must be at least one blob + if self.tx.blob_hashes.is_empty() { + return Err(InvalidTransaction::EmptyBlobs); + } + + // The field `to` deviates slightly from the semantics with the exception + // that it MUST NOT be nil and therefore must always represent + // a 20-byte address. This means that blob transactions cannot + // have the form of a create transaction. + if self.tx.transact_to.is_create() { + return Err(InvalidTransaction::BlobCreateTransaction); + } + + // all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG + for blob in self.tx.blob_hashes.iter() { + if blob[0] != VERSIONED_HASH_VERSION_KZG { + return Err(InvalidTransaction::BlobVersionNotSupported); + } + } + + // ensure the total blob gas spent is at most equal to the limit + // assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK + if self.tx.blob_hashes.len() > MAX_BLOB_NUMBER_PER_BLOCK as usize { + return Err(InvalidTransaction::TooManyBlobs); + } + } + } else { + if !self.tx.blob_hashes.is_empty() { + return Err(InvalidTransaction::BlobVersionedHashesNotSupported); + } + if self.tx.max_fee_per_blob_gas.is_some() { + return Err(InvalidTransaction::MaxFeePerBlobGasNotSupported); + } + } + + if SPEC::enabled(SpecId::PRAGUE) { + if !self.tx.eof_initcodes.is_empty() { + // If initcode is set other fields must be empty + if !self.tx.blob_hashes.is_empty() { + return Err(InvalidTransaction::BlobVersionedHashesNotSupported); + } + // EOF Create tx extends EIP-1559 tx. It must have max_fee_per_blob_gas + if self.tx.max_fee_per_blob_gas.is_some() { + return Err(InvalidTransaction::MaxFeePerBlobGasNotSupported); + } + // EOF Create must have a to address + if matches!(self.tx.transact_to, TransactTo::Call(_)) { + return Err(InvalidTransaction::EofCrateShouldHaveToAddress); + } + } else { + // If initcode is set check its bounds. + if self.tx.eof_initcodes.len() > 256 { + return Err(InvalidTransaction::EofInitcodesNumberLimit); + } + if self + .tx + .eof_initcodes_hashed + .iter() + .any(|(_, i)| i.len() >= MAX_INITCODE_SIZE) + { + return Err(InvalidTransaction::EofInitcodesSizeLimit); + } + } + } else { + // Initcode set when not supported. + if !self.tx.eof_initcodes.is_empty() { + return Err(InvalidTransaction::EofInitcodesNotSupported); + } + } + + Ok(()) + } + *) + Definition validate_tx (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC ], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::LONDON" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_priority_fee" + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let priority_fee := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "gt", + [] + |), + [ + priority_fee; + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_price" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::PriorityFeeGreaterThanMaxFee" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::CfgEnv", + "is_base_fee_check_disabled", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "cfg" + |) + ] + |)), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "lt", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "effective_gas_price", + [] + |), + [ M.read (| self |) ] + |) + |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "basefee" + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::GasPriceLessThanBasefee" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::CfgEnv", + "is_block_gas_limit_disabled", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "cfg" + |) + ] + |)), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "gt", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_limit" + |) + |) + ] + |) + |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "gas_limit" + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::CallerGasLimitMoreThanBlock" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::SHANGHAI" + [] + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::TransactTo", + "is_create", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "transact_to" + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ max_initcode_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "usize" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "usize" ], + "map", + [ + Ty.path "usize"; + Ty.function + [ Ty.tuple [ Ty.path "usize" ] ] + (Ty.path "usize") + ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "cfg" + |), + "revm_primitives::env::CfgEnv", + "limit_contract_code_size" + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let limit := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "usize", + "saturating_mul", + [] + |), + [ M.read (| limit |); Value.Integer 2 ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + M.read (| + M.get_constant (| + "revm_primitives::constants::MAX_INITCODE_SIZE" + |) + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "data" + |) + ] + |) + ] + |)) + (M.read (| max_initcode_size |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::CreateInitCodeSizeLimit" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "chain_id" + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let tx_chain_id := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| tx_chain_id |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "cfg" + |), + "revm_primitives::env::CfgEnv", + "chain_id" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::InvalidChainId" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + UnOp.Pure.not + (M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::BERLIN" + [] + ] + |)), + ltac:(M.monadic + (UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "access_list" + |) + ] + |)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::AccessListNotSupported" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CANCUN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "max_fee_per_blob_gas" + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let max := M.copy (| ฮณ0_0 |) in + let~ price := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "u128" ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::BlockEnv", + "get_blob_gasprice", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "block" + |) + ] + |); + M.read (| Value.String "already checked" |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "gt", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u128" ] + |), + [ M.read (| price |) ] + |) + |); + max + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::BlobGasPriceGreaterThanMax" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::EmptyBlobs" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::TransactTo", + "is_create", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "transact_to" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::BlobCreateTransaction" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.break (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let blob := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| + M.call_closure (| + M.get_trait_method (| + "core::ops::index::Index", + Ty.path + "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "usize" + ], + "index", + [] + |), + [ + M.read (| blob |); + Value.Integer 0 + ] + |) + |)) + (M.read (| + M.get_constant (| + "revm_primitives::constants::VERSIONED_HASH_VERSION_KZG" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::BlobVersionNotSupported" + [] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |) + ] + |)) + (M.rust_cast + (M.read (| + M.get_constant (| + "revm_primitives::constants::MAX_BLOB_NUMBER_PER_BLOCK" + |) + |))) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::TooManyBlobs" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::BlobVersionedHashesNotSupported" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + "is_some", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "max_fee_per_blob_gas" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::MaxFeePerBlobGasNotSupported" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::PRAGUE" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "eof_initcodes" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::BlobVersionedHashesNotSupported" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + "is_some", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "max_fee_per_blob_gas" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::MaxFeePerBlobGasNotSupported" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "transact_to" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Bool false |))) + ] + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::EofCrateShouldHaveToAddress" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "eof_initcodes" + |) + ] + |)) + (Value.Integer 256) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::EofInitcodesNumberLimit" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloy_primitives::bytes_::Bytes" + ], + [], + "any", + [ + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ]; + Ty.apply + (Ty.path "&") + [ + Ty.path + "alloy_primitives::bytes_::Bytes" + ] + ] + ] + ] + (Ty.path "bool") + ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path + "alloy_primitives::bytes_::Bytes"; + Ty.path + "std::hash::random::RandomState" + ], + "iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "eof_initcodes_hashed" + |) + ] + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let i := M.copy (| ฮณ0_1 |) in + BinOp.Pure.ge + (M.call_closure (| + M.get_associated_function (| + Ty.path + "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path + "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| i |) ] + |) + ] + |)) + (M.read (| + M.get_constant (| + "revm_primitives::constants::MAX_INITCODE_SIZE" + |) + |)))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::EofInitcodesSizeLimit" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "eof_initcodes" + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::EofInitcodesNotSupported" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_validate_tx : M.IsAssociatedFunction Self "validate_tx" validate_tx. + + (* + pub fn validate_tx_against_state( + &self, + account: &mut Account, + ) -> Result<(), InvalidTransaction> { + // EIP-3607: Reject transactions from senders with deployed code + // This EIP is introduced after london but there was no collision in past + // so we can leave it enabled always + if !self.cfg.is_eip3607_disabled() && account.info.code_hash != KECCAK_EMPTY { + return Err(InvalidTransaction::RejectCallerWithCode); + } + + // Check that the transaction's nonce is correct + if let Some(tx) = self.tx.nonce { + let state = account.info.nonce; + match tx.cmp(&state) { + Ordering::Greater => { + return Err(InvalidTransaction::NonceTooHigh { tx, state }); + } + Ordering::Less => { + return Err(InvalidTransaction::NonceTooLow { tx, state }); + } + _ => {} + } + } + + let mut balance_check = U256::from(self.tx.gas_limit) + .checked_mul(self.tx.gas_price) + .and_then(|gas_cost| gas_cost.checked_add(self.tx.value)) + .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; + + if SPEC::enabled(SpecId::CANCUN) { + // if the tx is not a blob tx, this will be None, so we add zero + let data_fee = self.calc_max_data_fee().unwrap_or_default(); + balance_check = balance_check + .checked_add(U256::from(data_fee)) + .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; + } + + // Check if account has enough balance for gas_limit*gas_price and value transfer. + // Transfer will be done inside `*_inner` functions. + if balance_check > account.info.balance { + if self.cfg.is_balance_check_disabled() { + // Add transaction cost to balance to ensure execution doesn't fail. + account.info.balance = balance_check; + } else { + return Err(InvalidTransaction::LackOfFundForMaxFee { + fee: Box::new(balance_check), + balance: Box::new(account.info.balance), + }); + } + } + + Ok(()) + } + *) + Definition validate_tx_against_state (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC ], [ self; account ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let account := M.alloc (| account |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::CfgEnv", + "is_eip3607_disabled", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "cfg" + |) + ] + |)), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "ne", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code_hash" + |); + M.get_constant (| + "revm_primitives::utilities::KECCAK_EMPTY" + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::RejectCallerWithCode" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "nonce" + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let tx := M.copy (| ฮณ0_0 |) in + let~ state := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "u64", + [], + "cmp", + [] + |), + [ tx; state ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::cmp::Ordering::Greater" |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructRecord + "revm_primitives::result::InvalidTransaction::NonceTooHigh" + [ + ("tx", M.read (| tx |)); + ("state", M.read (| state |)) + ] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::cmp::Ordering::Less" |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructRecord + "revm_primitives::result::InvalidTransaction::NonceTooLow" + [ + ("tx", M.read (| tx |)); + ("state", M.read (| state |)) + ] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ balance_check := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::result::InvalidTransaction" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "ok_or", + [ Ty.path "revm_primitives::result::InvalidTransaction" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + "and_then", + [ + Ty.path "ruint::Uint"; + Ty.function + [ Ty.tuple [ Ty.path "ruint::Uint" ] ] + (Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "checked_mul", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_limit" + |) + |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_price" + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let gas_cost := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "checked_add", + [] + |), + [ + M.read (| gas_cost |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "value" + |) + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + Value.StructTuple + "revm_primitives::result::InvalidTransaction::OverflowPaymentInTransaction" + [] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path "revm_primitives::result::InvalidTransaction" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "revm_primitives::result::InvalidTransaction" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CANCUN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ data_fee := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "calc_max_data_fee", + [] + |), + [ M.read (| self |) ] + |) + ] + |) + |) in + let~ _ := + M.write (| + balance_check, + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::result::InvalidTransaction" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + "ok_or", + [ Ty.path "revm_primitives::result::InvalidTransaction" + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "checked_add", + [] + |), + [ + M.read (| balance_check |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "ruint::Uint" ] + |), + [ M.read (| data_fee |) ] + |) + ] + |); + Value.StructTuple + "revm_primitives::result::InvalidTransaction::OverflowPaymentInTransaction" + [] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_primitives::result::InvalidTransaction" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::result::InvalidTransaction" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "gt", + [] + |), + [ + balance_check; + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::CfgEnv", + "is_balance_check_disabled", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::Env", + "cfg" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |), + M.read (| balance_check |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructRecord + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee" + [ + ("fee", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| balance_check |) ] + |)); + ("balance", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |) + ] + |)) + ] + ] + |) + |) + |) + |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_validate_tx_against_state : + M.IsAssociatedFunction Self "validate_tx_against_state" validate_tx_against_state. + End Impl_revm_primitives_env_Env. + + (* StructRecord + { + name := "CfgEnv"; + ty_params := []; + fields := + [ + ("chain_id", Ty.path "u64"); + ("kzg_settings", Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings"); + ("perf_analyse_created_bytecodes", Ty.path "revm_primitives::env::AnalysisKind"); + ("limit_contract_code_size", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "usize" ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_CfgEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CfgEnv". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::env::CfgEnv" + [ + ("chain_id", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u64", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "chain_id" + |) + ] + |)); + ("kzg_settings", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "kzg_settings" + |) + ] + |)); + ("perf_analyse_created_bytecodes", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::AnalysisKind", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "perf_analyse_created_bytecodes" + |) + ] + |)); + ("limit_contract_code_size", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "limit_contract_code_size" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_CfgEnv. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_CfgEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CfgEnv". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CfgEnv" |); + M.read (| Value.String "chain_id" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "chain_id" + |)); + M.read (| Value.String "kzg_settings" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "kzg_settings" + |)); + M.read (| Value.String "perf_analyse_created_bytecodes" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "perf_analyse_created_bytecodes" + |)); + M.read (| Value.String "limit_contract_code_size" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "limit_contract_code_size" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_CfgEnv. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_CfgEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CfgEnv". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_CfgEnv. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_CfgEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CfgEnv". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_CfgEnv. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_CfgEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CfgEnv". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_CfgEnv. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_CfgEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CfgEnv". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "chain_id" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::CfgEnv", + "chain_id" + |) + |)), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings", + [ Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "kzg_settings" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::CfgEnv", + "kzg_settings" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::AnalysisKind", + [ Ty.path "revm_primitives::env::AnalysisKind" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "perf_analyse_created_bytecodes" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::CfgEnv", + "perf_analyse_created_bytecodes" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "usize" ], + [ Ty.apply (Ty.path "core::option::Option") [ Ty.path "usize" ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::CfgEnv", + "limit_contract_code_size" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::CfgEnv", + "limit_contract_code_size" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_CfgEnv. + + Module Impl_revm_primitives_env_CfgEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CfgEnv". + + (* + pub fn with_chain_id(mut self, chain_id: u64) -> Self { + self.chain_id = chain_id; + self + } + *) + Definition with_chain_id (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; chain_id ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let chain_id := M.alloc (| chain_id |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + self, + "revm_primitives::env::CfgEnv", + "chain_id" + |), + M.read (| chain_id |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_chain_id : + M.IsAssociatedFunction Self "with_chain_id" with_chain_id. + + (* + pub fn is_eip3607_disabled(&self) -> bool { + false + } + *) + Definition is_eip3607_disabled (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Bool false)) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_eip3607_disabled : + M.IsAssociatedFunction Self "is_eip3607_disabled" is_eip3607_disabled. + + (* + pub fn is_balance_check_disabled(&self) -> bool { + false + } + *) + Definition is_balance_check_disabled (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Bool false)) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_balance_check_disabled : + M.IsAssociatedFunction Self "is_balance_check_disabled" is_balance_check_disabled. + + (* + pub fn is_gas_refund_disabled(&self) -> bool { + false + } + *) + Definition is_gas_refund_disabled (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Bool false)) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_gas_refund_disabled : + M.IsAssociatedFunction Self "is_gas_refund_disabled" is_gas_refund_disabled. + + (* + pub fn is_base_fee_check_disabled(&self) -> bool { + false + } + *) + Definition is_base_fee_check_disabled (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Bool false)) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_base_fee_check_disabled : + M.IsAssociatedFunction Self "is_base_fee_check_disabled" is_base_fee_check_disabled. + + (* + pub fn is_block_gas_limit_disabled(&self) -> bool { + false + } + *) + Definition is_block_gas_limit_disabled (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Bool false)) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_block_gas_limit_disabled : + M.IsAssociatedFunction Self "is_block_gas_limit_disabled" is_block_gas_limit_disabled. + + (* + pub fn is_beneficiary_reward_disabled(&self) -> bool { + false + } + *) + Definition is_beneficiary_reward_disabled (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Bool false)) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_beneficiary_reward_disabled : + M.IsAssociatedFunction Self "is_beneficiary_reward_disabled" is_beneficiary_reward_disabled. + End Impl_revm_primitives_env_CfgEnv. + + Module Impl_core_default_Default_for_revm_primitives_env_CfgEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CfgEnv". + + (* + fn default() -> Self { + Self { + chain_id: 1, + perf_analyse_created_bytecodes: AnalysisKind::default(), + limit_contract_code_size: None, + #[cfg(feature = "c-kzg")] + kzg_settings: crate::kzg::EnvKzgSettings::Default, + #[cfg(feature = "memory_limit")] + memory_limit: (1 << 32) - 1, + #[cfg(feature = "optional_balance_check")] + disable_balance_check: false, + #[cfg(feature = "optional_block_gas_limit")] + disable_block_gas_limit: false, + #[cfg(feature = "optional_eip3607")] + disable_eip3607: false, + #[cfg(feature = "optional_gas_refund")] + disable_gas_refund: false, + #[cfg(feature = "optional_no_base_fee")] + disable_base_fee: false, + #[cfg(feature = "optional_beneficiary_reward")] + disable_beneficiary_reward: false, + } + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::env::CfgEnv" + [ + ("chain_id", Value.Integer 1); + ("perf_analyse_created_bytecodes", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::env::AnalysisKind", + [], + "default", + [] + |), + [] + |)); + ("limit_contract_code_size", Value.StructTuple "core::option::Option::None" []); + ("kzg_settings", + Value.StructTuple "revm_primitives::kzg::env_settings::EnvKzgSettings::Default" []) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_env_CfgEnv. + + (* StructRecord + { + name := "BlockEnv"; + ty_params := []; + fields := + [ + ("number", Ty.path "ruint::Uint"); + ("coinbase", Ty.path "alloy_primitives::bits::address::Address"); + ("timestamp", Ty.path "ruint::Uint"); + ("gas_limit", Ty.path "ruint::Uint"); + ("basefee", Ty.path "ruint::Uint"); + ("difficulty", Ty.path "ruint::Uint"); + ("prevrandao", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ]); + ("blob_excess_gas_and_price", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_BlockEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlockEnv". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::env::BlockEnv" + [ + ("number", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "number" + |) + ] + |)); + ("coinbase", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "coinbase" + |) + ] + |)); + ("timestamp", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "timestamp" + |) + ] + |)); + ("gas_limit", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "gas_limit" + |) + ] + |)); + ("basefee", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "basefee" + |) + ] + |)); + ("difficulty", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "difficulty" + |) + ] + |)); + ("prevrandao", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "prevrandao" + |) + ] + |)); + ("blob_excess_gas_and_price", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "blob_excess_gas_and_price" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_BlockEnv. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_BlockEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlockEnv". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "number" |); + M.read (| Value.String "coinbase" |); + M.read (| Value.String "timestamp" |); + M.read (| Value.String "gas_limit" |); + M.read (| Value.String "basefee" |); + M.read (| Value.String "difficulty" |); + M.read (| Value.String "prevrandao" |); + M.read (| Value.String "blob_excess_gas_and_price" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "number" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "coinbase" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "timestamp" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "gas_limit" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "basefee" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "difficulty" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "prevrandao" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "blob_excess_gas_and_price" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "BlockEnv" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_BlockEnv. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_BlockEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlockEnv". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_BlockEnv. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_BlockEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlockEnv". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "number" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlockEnv", + "number" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "coinbase" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlockEnv", + "coinbase" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "timestamp" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlockEnv", + "timestamp" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "gas_limit" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlockEnv", + "gas_limit" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "basefee" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlockEnv", + "basefee" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "difficulty" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlockEnv", + "difficulty" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "prevrandao" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlockEnv", + "prevrandao" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "blob_excess_gas_and_price" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlockEnv", + "blob_excess_gas_and_price" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_BlockEnv. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_BlockEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlockEnv". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_BlockEnv. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_BlockEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlockEnv". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_BlockEnv. + + Module Impl_core_hash_Hash_for_revm_primitives_env_BlockEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlockEnv". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "number" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "coinbase" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "timestamp" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "gas_limit" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "basefee" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "difficulty" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "prevrandao" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ], + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "blob_excess_gas_and_price" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_env_BlockEnv. + + Module Impl_revm_primitives_env_BlockEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlockEnv". + + (* + pub fn set_blob_excess_gas_and_price(&mut self, excess_blob_gas: u64) { + self.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new(excess_blob_gas)); + } + *) + Definition set_blob_excess_gas_and_price (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; excess_blob_gas ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let excess_blob_gas := M.alloc (| excess_blob_gas |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "blob_excess_gas_and_price" + |), + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::BlobExcessGasAndPrice", + "new", + [] + |), + [ M.read (| excess_blob_gas |) ] + |) + ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_blob_excess_gas_and_price : + M.IsAssociatedFunction Self "set_blob_excess_gas_and_price" set_blob_excess_gas_and_price. + + (* + pub fn get_blob_gasprice(&self) -> Option { + self.blob_excess_gas_and_price + .as_ref() + .map(|a| a.blob_gasprice) + } + *) + Definition get_blob_gasprice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ] + ], + "map", + [ + Ty.path "u128"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ] + ] + ] + (Ty.path "u128") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "blob_excess_gas_and_price" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm_primitives::env::BlobExcessGasAndPrice", + "blob_gasprice" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get_blob_gasprice : + M.IsAssociatedFunction Self "get_blob_gasprice" get_blob_gasprice. + + (* + pub fn get_blob_excess_gas(&self) -> Option { + self.blob_excess_gas_and_price + .as_ref() + .map(|a| a.excess_blob_gas) + } + *) + Definition get_blob_excess_gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ] + ], + "map", + [ + Ty.path "u64"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ] + ] + ] + (Ty.path "u64") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::env::BlobExcessGasAndPrice" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlockEnv", + "blob_excess_gas_and_price" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm_primitives::env::BlobExcessGasAndPrice", + "excess_blob_gas" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get_blob_excess_gas : + M.IsAssociatedFunction Self "get_blob_excess_gas" get_blob_excess_gas. + + (* + pub fn clear(&mut self) { + *self = Self::default(); + } + *) + Definition clear (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.write (| + M.read (| self |), + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::env::BlockEnv", + [], + "default", + [] + |), + [] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_clear : M.IsAssociatedFunction Self "clear" clear. + End Impl_revm_primitives_env_BlockEnv. + + Module Impl_core_default_Default_for_revm_primitives_env_BlockEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlockEnv". + + (* + fn default() -> Self { + Self { + number: U256::ZERO, + coinbase: Address::ZERO, + timestamp: U256::from(1), + gas_limit: U256::MAX, + basefee: U256::ZERO, + difficulty: U256::ZERO, + prevrandao: Some(B256::ZERO), + blob_excess_gas_and_price: Some(BlobExcessGasAndPrice::new(0)), + } + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::env::BlockEnv" + [ + ("number", M.read (| M.get_constant (| "ruint::ZERO" |) |)); + ("coinbase", + M.read (| M.get_constant (| "alloy_primitives::bits::address::ZERO" |) |)); + ("timestamp", + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "from", [ Ty.path "i32" ] |), + [ Value.Integer 1 ] + |)); + ("gas_limit", M.read (| M.get_constant (| "ruint::MAX" |) |)); + ("basefee", M.read (| M.get_constant (| "ruint::ZERO" |) |)); + ("difficulty", M.read (| M.get_constant (| "ruint::ZERO" |) |)); + ("prevrandao", + Value.StructTuple + "core::option::Option::Some" + [ M.read (| M.get_constant (| "alloy_primitives::bits::fixed::ZERO" |) |) ]); + ("blob_excess_gas_and_price", + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::BlobExcessGasAndPrice", + "new", + [] + |), + [ Value.Integer 0 ] + |) + ]) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_env_BlockEnv. + + (* StructRecord + { + name := "TxEnv"; + ty_params := []; + fields := + [ + ("caller", Ty.path "alloy_primitives::bits::address::Address"); + ("gas_limit", Ty.path "u64"); + ("gas_price", Ty.path "ruint::Uint"); + ("transact_to", Ty.path "revm_primitives::env::TransactTo"); + ("value", Ty.path "ruint::Uint"); + ("data", Ty.path "alloy_primitives::bytes_::Bytes"); + ("nonce", Ty.apply (Ty.path "core::option::Option") [ Ty.path "u64" ]); + ("chain_id", Ty.apply (Ty.path "core::option::Option") [ Ty.path "u64" ]); + ("access_list", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ]; + Ty.path "alloc::alloc::Global" + ]); + ("gas_priority_fee", Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ]); + ("blob_hashes", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes"; Ty.path "alloc::alloc::Global" + ]); + ("max_fee_per_blob_gas", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ]); + ("eof_initcodes", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "alloc::alloc::Global" ]); + ("eof_initcodes_hashed", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "std::hash::random::RandomState" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_TxEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TxEnv". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::env::TxEnv" + [ + ("caller", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "caller" + |) + ] + |)); + ("gas_limit", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u64", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "gas_limit" + |) + ] + |)); + ("gas_price", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "gas_price" + |) + ] + |)); + ("transact_to", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::TransactTo", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "transact_to" + |) + ] + |)); + ("value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "value" + |) + ] + |)); + ("data", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "data" + |) + ] + |)); + ("nonce", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "u64" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "nonce" + |) + ] + |)); + ("chain_id", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "u64" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "chain_id" + |) + ] + |)); + ("access_list", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "access_list" + |) + ] + |)); + ("gas_priority_fee", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "gas_priority_fee" + |) + ] + |)); + ("blob_hashes", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |) + ] + |)); + ("max_fee_per_blob_gas", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "max_fee_per_blob_gas" + |) + ] + |)); + ("eof_initcodes", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "eof_initcodes" + |) + ] + |)); + ("eof_initcodes_hashed", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "eof_initcodes_hashed" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_TxEnv. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_TxEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TxEnv". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "caller" |); + M.read (| Value.String "gas_limit" |); + M.read (| Value.String "gas_price" |); + M.read (| Value.String "transact_to" |); + M.read (| Value.String "value" |); + M.read (| Value.String "data" |); + M.read (| Value.String "nonce" |); + M.read (| Value.String "chain_id" |); + M.read (| Value.String "access_list" |); + M.read (| Value.String "gas_priority_fee" |); + M.read (| Value.String "blob_hashes" |); + M.read (| Value.String "max_fee_per_blob_gas" |); + M.read (| Value.String "eof_initcodes" |); + M.read (| Value.String "eof_initcodes_hashed" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "caller" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "gas_limit" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "gas_price" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "transact_to" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "value" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "data" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "nonce" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "chain_id" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "access_list" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "gas_priority_fee" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "max_fee_per_blob_gas" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "eof_initcodes" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "eof_initcodes_hashed" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "TxEnv" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_TxEnv. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_TxEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TxEnv". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_TxEnv. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_TxEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TxEnv". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "caller" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "caller" + |) + ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "gas_limit" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "gas_limit" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "gas_price" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "gas_price" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::TransactTo", + [ Ty.path "revm_primitives::env::TransactTo" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "transact_to" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "transact_to" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "value" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "data" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "data" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "u64" ], + [ Ty.apply (Ty.path "core::option::Option") [ Ty.path "u64" ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "nonce" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "nonce" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "u64" ], + [ Ty.apply (Ty.path "core::option::Option") [ Ty.path "u64" ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "chain_id" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "chain_id" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "access_list" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "access_list" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + [ Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "gas_priority_fee" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "gas_priority_fee" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + [ Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "max_fee_per_blob_gas" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "max_fee_per_blob_gas" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "eof_initcodes" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "eof_initcodes" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "eof_initcodes_hashed" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::TxEnv", + "eof_initcodes_hashed" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_TxEnv. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_TxEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TxEnv". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_TxEnv. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_TxEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TxEnv". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun + ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun + ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun + ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple + [] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_TxEnv. + + (* + Enum TxType + { + ty_params := []; + variants := + [ + { + name := "Legacy"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Eip1559"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BlobTx"; + item := StructTuple []; + discriminant := None; + }; + { + name := "EofCreate"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_revm_primitives_env_TxEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TxEnv". + + (* + pub fn get_total_blob_gas(&self) -> u64 { + GAS_PER_BLOB * self.blob_hashes.len() as u64 + } + *) + Definition get_total_blob_gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.mul + Integer.U64 + (M.read (| M.get_constant (| "revm_primitives::constants::GAS_PER_BLOB" |) |)) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::TxEnv", + "blob_hashes" + |) + ] + |))))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get_total_blob_gas : + M.IsAssociatedFunction Self "get_total_blob_gas" get_total_blob_gas. + + (* + pub fn clear(&mut self) { + *self = Self::default(); + } + *) + Definition clear (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.write (| + M.read (| self |), + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::env::TxEnv", + [], + "default", + [] + |), + [] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_clear : M.IsAssociatedFunction Self "clear" clear. + End Impl_revm_primitives_env_TxEnv. + + Module Impl_core_default_Default_for_revm_primitives_env_TxEnv. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TxEnv". + + (* + fn default() -> Self { + Self { + caller: Address::ZERO, + gas_limit: u64::MAX, + gas_price: U256::ZERO, + gas_priority_fee: None, + transact_to: TransactTo::Call(Address::ZERO), // will do nothing + value: U256::ZERO, + data: Bytes::new(), + chain_id: None, + nonce: None, + access_list: Vec::new(), + blob_hashes: Vec::new(), + max_fee_per_blob_gas: None, + eof_initcodes: Vec::new(), + eof_initcodes_hashed: HashMap::new(), + #[cfg(feature = "optimism")] + optimism: OptimismFields::default(), + } + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::env::TxEnv" + [ + ("caller", M.read (| M.get_constant (| "alloy_primitives::bits::address::ZERO" |) |)); + ("gas_limit", M.read (| M.get_constant (| "core::num::MAX" |) |)); + ("gas_price", M.read (| M.get_constant (| "ruint::ZERO" |) |)); + ("gas_priority_fee", Value.StructTuple "core::option::Option::None" []); + ("transact_to", + Value.StructTuple + "revm_primitives::env::TransactTo::Call" + [ M.read (| M.get_constant (| "alloy_primitives::bits::address::ZERO" |) |) ]); + ("value", M.read (| M.get_constant (| "ruint::ZERO" |) |)); + ("data", + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |)); + ("chain_id", Value.StructTuple "core::option::Option::None" []); + ("nonce", Value.StructTuple "core::option::Option::None" []); + ("access_list", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |)); + ("blob_hashes", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |)); + ("max_fee_per_blob_gas", Value.StructTuple "core::option::Option::None" []); + ("eof_initcodes", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [] + |)); + ("eof_initcodes_hashed", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_env_TxEnv. + + (* StructRecord + { + name := "BlobExcessGasAndPrice"; + ty_params := []; + fields := [ ("excess_blob_gas", Ty.path "u64"); ("blob_gasprice", Ty.path "u128") ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_BlobExcessGasAndPrice. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlobExcessGasAndPrice". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::env::BlobExcessGasAndPrice" + [ + ("excess_blob_gas", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u64", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlobExcessGasAndPrice", + "excess_blob_gas" + |) + ] + |)); + ("blob_gasprice", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u128", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlobExcessGasAndPrice", + "blob_gasprice" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_BlobExcessGasAndPrice. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_BlobExcessGasAndPrice. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlobExcessGasAndPrice". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "BlobExcessGasAndPrice" |); + M.read (| Value.String "excess_blob_gas" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlobExcessGasAndPrice", + "excess_blob_gas" + |)); + M.read (| Value.String "blob_gasprice" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlobExcessGasAndPrice", + "blob_gasprice" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_BlobExcessGasAndPrice. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_BlobExcessGasAndPrice. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlobExcessGasAndPrice". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_BlobExcessGasAndPrice. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_BlobExcessGasAndPrice. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlobExcessGasAndPrice". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlobExcessGasAndPrice", + "excess_blob_gas" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlobExcessGasAndPrice", + "excess_blob_gas" + |) + |)), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlobExcessGasAndPrice", + "blob_gasprice" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::BlobExcessGasAndPrice", + "blob_gasprice" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_BlobExcessGasAndPrice. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_BlobExcessGasAndPrice. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlobExcessGasAndPrice". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_BlobExcessGasAndPrice. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_BlobExcessGasAndPrice. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlobExcessGasAndPrice". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_BlobExcessGasAndPrice. + + Module Impl_core_hash_Hash_for_revm_primitives_env_BlobExcessGasAndPrice. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlobExcessGasAndPrice". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u64", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlobExcessGasAndPrice", + "excess_blob_gas" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u128", [], "hash", [ __H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::BlobExcessGasAndPrice", + "blob_gasprice" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_env_BlobExcessGasAndPrice. + + Module Impl_revm_primitives_env_BlobExcessGasAndPrice. + Definition Self : Ty.t := Ty.path "revm_primitives::env::BlobExcessGasAndPrice". + + (* + pub fn new(excess_blob_gas: u64) -> Self { + let blob_gasprice = calc_blob_gasprice(excess_blob_gas); + Self { + excess_blob_gas, + blob_gasprice, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ excess_blob_gas ] => + ltac:(M.monadic + (let excess_blob_gas := M.alloc (| excess_blob_gas |) in + M.read (| + let~ blob_gasprice := + M.alloc (| + M.call_closure (| + M.get_function (| "revm_primitives::utilities::calc_blob_gasprice", [] |), + [ M.read (| excess_blob_gas |) ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm_primitives::env::BlobExcessGasAndPrice" + [ + ("excess_blob_gas", M.read (| excess_blob_gas |)); + ("blob_gasprice", M.read (| blob_gasprice |)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + End Impl_revm_primitives_env_BlobExcessGasAndPrice. + + (* + Enum TransactTo + { + ty_params := []; + variants := + [ + { + name := "Call"; + item := StructTuple [ Ty.path "alloy_primitives::bits::address::Address" ]; + discriminant := None; + }; + { + name := "Create"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_TransactTo. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TransactTo". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::env::TransactTo::Call" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::env::TransactTo::Create" |) in + M.alloc (| Value.StructTuple "revm_primitives::env::TransactTo::Create" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_TransactTo. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_TransactTo. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TransactTo". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Call" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::env::TransactTo::Create" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Create" |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_TransactTo. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_TransactTo. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TransactTo". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_TransactTo. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_TransactTo. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TransactTo". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::env::TransactTo" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::env::TransactTo" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool true |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_TransactTo. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_TransactTo. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TransactTo". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_TransactTo. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_TransactTo. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TransactTo". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_TransactTo. + + Module Impl_core_hash_Hash_for_revm_primitives_env_TransactTo. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TransactTo". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::env::TransactTo" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_env_TransactTo. + + Module Impl_revm_primitives_env_TransactTo. + Definition Self : Ty.t := Ty.path "revm_primitives::env::TransactTo". + + (* + pub fn call(address: Address) -> Self { + Self::Call(address) + } + *) + Definition call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ address ] => + ltac:(M.monadic + (let address := M.alloc (| address |) in + Value.StructTuple "revm_primitives::env::TransactTo::Call" [ M.read (| address |) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_call : M.IsAssociatedFunction Self "call" call. + + (* + pub fn create() -> Self { + Self::Create + } + *) + Definition create (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => ltac:(M.monadic (Value.StructTuple "revm_primitives::env::TransactTo::Create" [])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_create : M.IsAssociatedFunction Self "create" create. + + (* + pub fn is_call(&self) -> bool { + matches!(self, Self::Call(_)) + } + *) + Definition is_call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_call : M.IsAssociatedFunction Self "is_call" is_call. + + (* + pub fn is_create(&self) -> bool { + matches!(self, Self::Create) + } + *) + Definition is_create (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::env::TransactTo::Create" |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_create : M.IsAssociatedFunction Self "is_create" is_create. + End Impl_revm_primitives_env_TransactTo. + + (* + Enum CreateScheme + { + ty_params := []; + variants := + [ + { + name := "Create"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Create2"; + item := StructRecord [ ("salt", Ty.path "ruint::Uint") ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_CreateScheme. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CreateScheme". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_CreateScheme. + + Module Impl_core_marker_Copy_for_revm_primitives_env_CreateScheme. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CreateScheme". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_env_CreateScheme. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_CreateScheme. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CreateScheme". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::env::CreateScheme::Create" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Create" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::env::CreateScheme::Create2", + "salt" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Create2" |); + M.read (| Value.String "salt" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_CreateScheme. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_CreateScheme. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CreateScheme". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_CreateScheme. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_CreateScheme. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CreateScheme". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_CreateScheme. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_CreateScheme. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CreateScheme". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_CreateScheme. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_CreateScheme. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CreateScheme". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::env::CreateScheme" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::env::CreateScheme" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::env::CreateScheme::Create2", + "salt" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::env::CreateScheme::Create2", + "salt" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool true |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_CreateScheme. + + Module Impl_core_hash_Hash_for_revm_primitives_env_CreateScheme. + Definition Self : Ty.t := Ty.path "revm_primitives::env::CreateScheme". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::env::CreateScheme" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::env::CreateScheme::Create2", + "salt" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_env_CreateScheme. + + (* + Enum AnalysisKind + { + ty_params := []; + variants := + [ + { + name := "Raw"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Analyse"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_AnalysisKind. + Definition Self : Ty.t := Ty.path "revm_primitives::env::AnalysisKind". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := M.is_struct_tuple (| ฮณ, "revm_primitives::env::AnalysisKind::Raw" |) in + M.alloc (| Value.StructTuple "revm_primitives::env::AnalysisKind::Raw" [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::env::AnalysisKind::Analyse" |) in + M.alloc (| + Value.StructTuple "revm_primitives::env::AnalysisKind::Analyse" [] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_AnalysisKind. + + Module Impl_core_default_Default_for_revm_primitives_env_AnalysisKind. + Definition Self : Ty.t := Ty.path "revm_primitives::env::AnalysisKind". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::env::AnalysisKind::Analyse" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_env_AnalysisKind. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_AnalysisKind. + Definition Self : Ty.t := Ty.path "revm_primitives::env::AnalysisKind". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::env::AnalysisKind::Raw" |) in + M.alloc (| M.read (| Value.String "Raw" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::env::AnalysisKind::Analyse" + |) in + M.alloc (| M.read (| Value.String "Analyse" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_AnalysisKind. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_AnalysisKind. + Definition Self : Ty.t := Ty.path "revm_primitives::env::AnalysisKind". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_AnalysisKind. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_AnalysisKind. + Definition Self : Ty.t := Ty.path "revm_primitives::env::AnalysisKind". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_AnalysisKind. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_AnalysisKind. + Definition Self : Ty.t := Ty.path "revm_primitives::env::AnalysisKind". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_AnalysisKind. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_AnalysisKind. + Definition Self : Ty.t := Ty.path "revm_primitives::env::AnalysisKind". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::env::AnalysisKind" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::env::AnalysisKind" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_AnalysisKind. + + Module Impl_core_hash_Hash_for_revm_primitives_env_AnalysisKind. + Definition Self : Ty.t := Ty.path "revm_primitives::env::AnalysisKind". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::env::AnalysisKind" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_env_AnalysisKind. +End env. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/env/handler_cfg.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/env/handler_cfg.md new file mode 100644 index 00000000..297602de --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/env/handler_cfg.md @@ -0,0 +1,1186 @@ +# ๐Ÿ“ handler_cfg.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/env/handler_cfg.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module env. + Module handler_cfg. + (* StructRecord + { + name := "HandlerCfg"; + ty_params := []; + fields := [ ("spec_id", Ty.path "revm_primitives::specification::SpecId") ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_handler_cfg_HandlerCfg. + + Module Impl_core_marker_Copy_for_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_env_handler_cfg_HandlerCfg. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "HandlerCfg" |); + M.read (| Value.String "spec_id" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_handler_cfg_HandlerCfg. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_handler_cfg_HandlerCfg. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_handler_cfg_HandlerCfg. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_handler_cfg_HandlerCfg. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::specification::SpecId", + [ Ty.path "revm_primitives::specification::SpecId" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_handler_cfg_HandlerCfg. + + Module Impl_core_hash_Hash_for_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::specification::SpecId", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |); + M.read (| state |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_env_handler_cfg_HandlerCfg. + + Module Impl_core_default_Default_for_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + (* + fn default() -> Self { + Self::new(SpecId::default()) + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + "new", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::specification::SpecId", + [], + "default", + [] + |), + [] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_env_handler_cfg_HandlerCfg. + + Module Impl_revm_primitives_env_handler_cfg_HandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::HandlerCfg". + + (* + pub fn new(spec_id: SpecId) -> Self { + cfg_if::cfg_if! { + if #[cfg(all(feature = "optimism-default-handler", + not(feature = "negate-optimism-default-handler")))] { + let is_optimism = true; + } else if #[cfg(feature = "optimism")] { + let is_optimism = false; + } + } + Self { + spec_id, + #[cfg(feature = "optimism")] + is_optimism, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + Value.StructRecord + "revm_primitives::env::handler_cfg::HandlerCfg" + [ ("spec_id", M.read (| spec_id |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn is_optimism(&self) -> bool { + cfg_if::cfg_if! { + if #[cfg(feature = "optimism")] { + self.is_optimism + } else { + false + } + } + } + *) + Definition is_optimism (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Bool false)) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_optimism : M.IsAssociatedFunction Self "is_optimism" is_optimism. + End Impl_revm_primitives_env_handler_cfg_HandlerCfg. + + (* StructRecord + { + name := "CfgEnvWithHandlerCfg"; + ty_params := []; + fields := + [ + ("cfg_env", Ty.path "revm_primitives::env::CfgEnv"); + ("handler_cfg", Ty.path "revm_primitives::env::handler_cfg::HandlerCfg") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg" + [ + ("cfg_env", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::CfgEnv", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "cfg_env" + |) + ] + |)); + ("handler_cfg", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "handler_cfg" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CfgEnvWithHandlerCfg" |); + M.read (| Value.String "cfg_env" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "cfg_env" + |)); + M.read (| Value.String "handler_cfg" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "handler_cfg" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::CfgEnv", + [ Ty.path "revm_primitives::env::CfgEnv" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "cfg_env" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "cfg_env" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + [ Ty.path "revm_primitives::env::handler_cfg::HandlerCfg" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "handler_cfg" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "handler_cfg" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + + Module Impl_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg". + + (* + pub fn new(cfg_env: CfgEnv, handler_cfg: HandlerCfg) -> Self { + Self { + cfg_env, + handler_cfg, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ cfg_env; handler_cfg ] => + ltac:(M.monadic + (let cfg_env := M.alloc (| cfg_env |) in + let handler_cfg := M.alloc (| handler_cfg |) in + Value.StructRecord + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg" + [ ("cfg_env", M.read (| cfg_env |)); ("handler_cfg", M.read (| handler_cfg |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn new_with_spec_id(cfg_env: CfgEnv, spec_id: SpecId) -> Self { + Self::new(cfg_env, HandlerCfg::new(spec_id)) + } + *) + Definition new_with_spec_id (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ cfg_env; spec_id ] => + ltac:(M.monadic + (let cfg_env := M.alloc (| cfg_env |) in + let spec_id := M.alloc (| spec_id |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "new", + [] + |), + [ + M.read (| cfg_env |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + "new", + [] + |), + [ M.read (| spec_id |) ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_with_spec_id : + M.IsAssociatedFunction Self "new_with_spec_id" new_with_spec_id. + End Impl_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + + Module Impl_core_ops_deref_DerefMut_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg". + + (* + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.cfg_env + } + *) + Definition deref_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "cfg_env" + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::DerefMut" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("deref_mut", InstanceField.Method deref_mut) ]. + End Impl_core_ops_deref_DerefMut_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + + Module Impl_core_ops_deref_Deref_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg". + + (* type Target = CfgEnv; *) + Definition _Target : Ty.t := Ty.path "revm_primitives::env::CfgEnv". + + (* + fn deref(&self) -> &Self::Target { + &self.cfg_env + } + *) + Definition deref (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "cfg_env" + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::Deref" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("Target", InstanceField.Ty _Target); ("deref", InstanceField.Method deref) ]. + End Impl_core_ops_deref_Deref_for_revm_primitives_env_handler_cfg_CfgEnvWithHandlerCfg. + + (* StructRecord + { + name := "EnvWithHandlerCfg"; + ty_params := []; + fields := + [ + ("env", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ]); + ("handler_cfg", Ty.path "revm_primitives::env::handler_cfg::HandlerCfg") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg" + [ + ("env", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "env" + |) + ] + |)); + ("handler_cfg", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "handler_cfg" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + + Module Impl_core_fmt_Debug_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "EnvWithHandlerCfg" |); + M.read (| Value.String "env" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "env" + |)); + M.read (| Value.String "handler_cfg" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "handler_cfg" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + + Module Impl_core_default_Default_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg" + [ + ("env", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ], + [], + "default", + [] + |), + [] + |)); + ("handler_cfg", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + + Module Impl_core_cmp_Eq_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "env" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "env" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + [ Ty.path "revm_primitives::env::handler_cfg::HandlerCfg" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "handler_cfg" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "handler_cfg" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + + Module Impl_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + (* + pub fn new(env: Box, handler_cfg: HandlerCfg) -> Self { + Self { env, handler_cfg } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ env; handler_cfg ] => + ltac:(M.monadic + (let env := M.alloc (| env |) in + let handler_cfg := M.alloc (| handler_cfg |) in + Value.StructRecord + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg" + [ ("env", M.read (| env |)); ("handler_cfg", M.read (| handler_cfg |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn new_with_spec_id(env: Box, spec_id: SpecId) -> Self { + Self::new(env, HandlerCfg::new(spec_id)) + } + *) + Definition new_with_spec_id (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ env; spec_id ] => + ltac:(M.monadic + (let env := M.alloc (| env |) in + let spec_id := M.alloc (| spec_id |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "new", + [] + |), + [ + M.read (| env |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + "new", + [] + |), + [ M.read (| spec_id |) ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_with_spec_id : + M.IsAssociatedFunction Self "new_with_spec_id" new_with_spec_id. + + (* + pub fn new_with_cfg_env(cfg: CfgEnvWithHandlerCfg, block: BlockEnv, tx: TxEnv) -> Self { + Self::new(Env::boxed(cfg.cfg_env, block, tx), cfg.handler_cfg) + } + *) + Definition new_with_cfg_env (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ cfg; block; tx ] => + ltac:(M.monadic + (let cfg := M.alloc (| cfg |) in + let block := M.alloc (| block |) in + let tx := M.alloc (| tx |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| Ty.path "revm_primitives::env::Env", "boxed", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + cfg, + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "cfg_env" + |) + |); + M.read (| block |); + M.read (| tx |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + cfg, + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "handler_cfg" + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_with_cfg_env : + M.IsAssociatedFunction Self "new_with_cfg_env" new_with_cfg_env. + + (* + pub const fn spec_id(&self) -> SpecId { + self.handler_cfg.spec_id + } + *) + Definition spec_id (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "handler_cfg" + |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_spec_id : M.IsAssociatedFunction Self "spec_id" spec_id. + End Impl_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + + Module Impl_core_ops_deref_DerefMut_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + (* + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.env + } + *) + Definition deref_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "env" + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::DerefMut" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("deref_mut", InstanceField.Method deref_mut) ]. + End Impl_core_ops_deref_DerefMut_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + + Module Impl_core_ops_deref_Deref_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + Definition Self : Ty.t := Ty.path "revm_primitives::env::handler_cfg::EnvWithHandlerCfg". + + (* type Target = Env; *) + Definition _Target : Ty.t := Ty.path "revm_primitives::env::Env". + + (* + fn deref(&self) -> &Self::Target { + &self.env + } + *) + Definition deref (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "env" + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::Deref" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("Target", InstanceField.Ty _Target); ("deref", InstanceField.Method deref) ]. + End Impl_core_ops_deref_Deref_for_revm_primitives_env_handler_cfg_EnvWithHandlerCfg. + End handler_cfg. +End env. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/kzg/env_settings.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/kzg/env_settings.md new file mode 100644 index 00000000..f6e25fc0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/kzg/env_settings.md @@ -0,0 +1,650 @@ +# ๐Ÿ“ env_settings.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/kzg/env_settings.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module kzg. + Module env_settings. + (* + Enum EnvKzgSettings + { + ty_params := []; + variants := + [ + { + name := "Default"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Custom"; + item := + StructTuple + [ + Ty.apply + (Ty.path "alloc::sync::Arc") + [ Ty.path "c_kzg::bindings::KZGSettings"; Ty.path "alloc::alloc::Global" ] + ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Default" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Default" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Custom", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Custom" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + + Module Impl_core_clone_Clone_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Default" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::kzg::env_settings::EnvKzgSettings::Default" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Custom", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::kzg::env_settings::EnvKzgSettings::Custom" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.path "c_kzg::bindings::KZGSettings"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + + Module Impl_core_default_Default_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple "revm_primitives::kzg::env_settings::EnvKzgSettings::Default" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + + Module Impl_core_cmp_Eq_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings". + + (* + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Default, Self::Default) => true, + (Self::Custom(a), Self::Custom(b)) => Arc::ptr_eq(a, b), + _ => false, + } + } + *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let _ := + M.is_struct_tuple (| + ฮณ0_0, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Default" + |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let _ := + M.is_struct_tuple (| + ฮณ0_1, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Default" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Custom", + 0 + |) in + let a := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Custom", + 0 + |) in + let b := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.path "c_kzg::bindings::KZGSettings"; + Ty.path "alloc::alloc::Global" + ], + "ptr_eq", + [] + |), + [ M.read (| a |); M.read (| b |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + + Module Impl_core_hash_Hash_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings". + + (* + fn hash(&self, state: &mut H) { + core::mem::discriminant(self).hash(state); + match self { + Self::Default => {} + Self::Custom(settings) => Arc::as_ptr(settings).hash(state), + } + } + *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "core::mem::Discriminant") + [ Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings" ], + [], + "hash", + [ H ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::discriminant", + [ Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings" ] + |), + [ M.read (| self |) ] + |) + |); + M.read (| state |) + ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Default" + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Custom", + 0 + |) in + let settings := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply (Ty.path "*const") [ Ty.path "c_kzg::bindings::KZGSettings" ], + [], + "hash", + [ H ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.path "c_kzg::bindings::KZGSettings"; + Ty.path "alloc::alloc::Global" + ], + "as_ptr", + [] + |), + [ M.read (| settings |) ] + |) + |); + M.read (| state |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_kzg_env_settings_EnvKzgSettings. + + Module Impl_revm_primitives_kzg_env_settings_EnvKzgSettings. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::env_settings::EnvKzgSettings". + + (* + pub fn get(&self) -> &KzgSettings { + match self { + Self::Default => { + static DEFAULT: OnceBox = OnceBox::new(); + DEFAULT.get_or_init(|| { + let settings = + KzgSettings::load_trusted_setup(G1_POINTS.as_ref(), G2_POINTS.as_ref()) + .expect("failed to load default trusted setup"); + Box::new(settings) + }) + } + Self::Custom(settings) => settings, + } + } + *) + Definition get (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Default" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "once_cell::race::once_box::OnceBox") + [ Ty.path "c_kzg::bindings::KZGSettings" ], + "get_or_init", + [ + Ty.function + [ Ty.tuple [] ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "c_kzg::bindings::KZGSettings"; + Ty.path "alloc::alloc::Global" + ]) + ] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::kzg::env_settings::get::DEFAULT" + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.read (| + let~ settings := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "c_kzg::bindings::KZGSettings"; + Ty.path "c_kzg::bindings::Error" + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "c_kzg::bindings::KZGSettings", + "load_trusted_setup", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_trait_method (| + "core::convert::AsRef", + Ty.path + "revm_primitives::kzg::trusted_setup_points::G1Points", + [ + Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "array") + [ Ty.path "u8" ] + ] + ], + "as_ref", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::kzg::trusted_setup_points::G1_POINTS" + |) + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_trait_method (| + "core::convert::AsRef", + Ty.path + "revm_primitives::kzg::trusted_setup_points::G2Points", + [ + Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "array") + [ Ty.path "u8" ] + ] + ], + "as_ref", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::kzg::trusted_setup_points::G2_POINTS" + |) + |) + ] + |)) + ] + |); + M.read (| + Value.String + "failed to load default trusted setup" + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "c_kzg::bindings::KZGSettings"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ M.read (| settings |) ] + |) + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::kzg::env_settings::EnvKzgSettings::Custom", + 0 + |) in + let settings := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.path "c_kzg::bindings::KZGSettings"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ M.read (| settings |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get : M.IsAssociatedFunction Self "get" get. + End Impl_revm_primitives_kzg_env_settings_EnvKzgSettings. + End env_settings. +End kzg. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/kzg/trusted_setup_points.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/kzg/trusted_setup_points.md new file mode 100644 index 00000000..919dabe8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/kzg/trusted_setup_points.md @@ -0,0 +1,2520 @@ +# ๐Ÿ“ trusted_setup_points.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/kzg/trusted_setup_points.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module kzg. + Module trusted_setup_points. + Definition value_NUM_G1_POINTS : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 4096 |))). + + Definition value_NUM_G2_POINTS : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 65 |))). + + (* StructTuple + { + name := "G1Points"; + ty_params := []; + fields := [ Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_primitives_kzg_trusted_setup_points_G1Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "G1Points" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G1Points", + 0 + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_kzg_trusted_setup_points_G1Points. + + Module Impl_core_clone_Clone_for_revm_primitives_kzg_trusted_setup_points_G1Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::G1Points" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G1Points", + 0 + |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_kzg_trusted_setup_points_G1Points. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_kzg_trusted_setup_points_G1Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_kzg_trusted_setup_points_G1Points. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_kzg_trusted_setup_points_G1Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [ Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G1Points", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_primitives::kzg::trusted_setup_points::G1Points", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_kzg_trusted_setup_points_G1Points. + + Module Impl_core_convert_AsRef_array_array_u8_for_revm_primitives_kzg_trusted_setup_points_G1Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points". + + (* AsRef *) + Definition as_ref (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G1Points", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::AsRef" + Self + (* Trait polymorphic types *) + [ (* T *) Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] ] + (* Instance *) [ ("as_ref", InstanceField.Method as_ref) ]. + End Impl_core_convert_AsRef_array_array_u8_for_revm_primitives_kzg_trusted_setup_points_G1Points. + + Module Impl_core_convert_AsMut_array_array_u8_for_revm_primitives_kzg_trusted_setup_points_G1Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points". + + (* AsMut *) + Definition as_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G1Points", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::AsMut" + Self + (* Trait polymorphic types *) + [ (* T *) Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] ] + (* Instance *) [ ("as_mut", InstanceField.Method as_mut) ]. + End Impl_core_convert_AsMut_array_array_u8_for_revm_primitives_kzg_trusted_setup_points_G1Points. + + Module Impl_core_ops_deref_Deref_for_revm_primitives_kzg_trusted_setup_points_G1Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points". + + (* Deref *) + Definition _Target : Ty.t := + Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ]. + + (* Deref *) + Definition deref (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G1Points", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::Deref" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("Target", InstanceField.Ty _Target); ("deref", InstanceField.Method deref) ]. + End Impl_core_ops_deref_Deref_for_revm_primitives_kzg_trusted_setup_points_G1Points. + + Module Impl_core_ops_deref_DerefMut_for_revm_primitives_kzg_trusted_setup_points_G1Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points". + + (* DerefMut *) + Definition deref_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G1Points", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::DerefMut" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("deref_mut", InstanceField.Method deref_mut) ]. + End Impl_core_ops_deref_DerefMut_for_revm_primitives_kzg_trusted_setup_points_G1Points. + + Module Impl_core_default_Default_for_revm_primitives_kzg_trusted_setup_points_G1Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points". + + (* + fn default() -> Self { + Self([[0; BYTES_PER_G1_POINT]; NUM_G1_POINTS]) + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::G1Points" + [ repeat (repeat (Value.Integer 0) 48) 4096 ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_kzg_trusted_setup_points_G1Points. + + (* StructTuple + { + name := "G2Points"; + ty_params := []; + fields := [ Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "G2Points" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G2Points", + 0 + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_clone_Clone_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::G2Points" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G2Points", + 0 + |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_cmp_Eq_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [ Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G2Points", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_primitives::kzg::trusted_setup_points::G2Points", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_convert_AsRef_array_array_u8_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + (* AsRef *) + Definition as_ref (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G2Points", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::AsRef" + Self + (* Trait polymorphic types *) + [ (* T *) Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] ] + (* Instance *) [ ("as_ref", InstanceField.Method as_ref) ]. + End Impl_core_convert_AsRef_array_array_u8_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_convert_AsMut_array_array_u8_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + (* AsMut *) + Definition as_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G2Points", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::AsMut" + Self + (* Trait polymorphic types *) + [ (* T *) Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] ] + (* Instance *) [ ("as_mut", InstanceField.Method as_mut) ]. + End Impl_core_convert_AsMut_array_array_u8_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_ops_deref_Deref_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + (* Deref *) + Definition _Target : Ty.t := + Ty.apply (Ty.path "array") [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ]. + + (* Deref *) + Definition deref (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G2Points", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::Deref" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("Target", InstanceField.Ty _Target); ("deref", InstanceField.Method deref) ]. + End Impl_core_ops_deref_Deref_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_ops_deref_DerefMut_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + (* DerefMut *) + Definition deref_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::kzg::trusted_setup_points::G2Points", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::DerefMut" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("deref_mut", InstanceField.Method deref_mut) ]. + End Impl_core_ops_deref_DerefMut_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Module Impl_core_default_Default_for_revm_primitives_kzg_trusted_setup_points_G2Points. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points". + + (* + fn default() -> Self { + Self([[0; BYTES_PER_G2_POINT]; NUM_G2_POINTS]) + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::G2Points" + [ repeat (repeat (Value.Integer 0) 96) 65 ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_kzg_trusted_setup_points_G2Points. + + Definition value_G1_POINTS : Value.t := + M.run + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::kzg::trusted_setup_points::G1_POINTS::BYTES" + |) + |) + ] + |)) + (M.call_closure (| + M.get_function (| + "core::mem::size_of", + [ Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points" ] + |), + [] + |))) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic", [] |), + [ + M.read (| + Value.String + "assertion failed: BYTES.len() == core::mem::size_of::()" + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "cast", + [ Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::kzg::trusted_setup_points::G1_POINTS::BYTES" + |) + |) + ] + |) + ] + |) + |))). + + Module G1_POINTS. + Definition value_BYTES : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| (* Unsize *) M.pointer_coercion (M.read (| UnsupportedLiteral |)) |))). + End G1_POINTS. + + Definition value_G2_POINTS : Value.t := + M.run + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "len", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::kzg::trusted_setup_points::G2_POINTS::BYTES" + |) + |) + ] + |)) + (M.call_closure (| + M.get_function (| + "core::mem::size_of", + [ Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points" ] + |), + [] + |))) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic", [] |), + [ + M.read (| + Value.String + "assertion failed: BYTES.len() == core::mem::size_of::()" + |) + ] + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "cast", + [ Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "as_ptr", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::kzg::trusted_setup_points::G2_POINTS::BYTES" + |) + |) + ] + |) + ] + |) + |))). + + Module G2_POINTS. + Definition value_BYTES : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| (* Unsize *) M.pointer_coercion (M.read (| UnsupportedLiteral |)) |))). + End G2_POINTS. + + (* + pub fn parse_kzg_trusted_setup( + trusted_setup: &str, + ) -> Result<(Box, Box), KzgErrors> { + let mut lines = trusted_setup.lines(); + + // load number of points + let n_g1 = lines + .next() + .ok_or(KzgErrors::FileFormatError)? + .parse::() + .map_err(|_| KzgErrors::ParseError)?; + let n_g2 = lines + .next() + .ok_or(KzgErrors::FileFormatError)? + .parse::() + .map_err(|_| KzgErrors::ParseError)?; + + if n_g1 != NUM_G1_POINTS { + return Err(KzgErrors::MismatchedNumberOfPoints); + } + + if n_g2 != NUM_G2_POINTS { + return Err(KzgErrors::MismatchedNumberOfPoints); + } + + // load g1 points + let mut g1_points = Box::::default(); + for bytes in &mut g1_points.0 { + let line = lines.next().ok_or(KzgErrors::FileFormatError)?; + crate::hex::decode_to_slice(line, bytes).map_err(|_| KzgErrors::ParseError)?; + } + + // load g2 points + let mut g2_points = Box::::default(); + for bytes in &mut g2_points.0 { + let line = lines.next().ok_or(KzgErrors::FileFormatError)?; + crate::hex::decode_to_slice(line, bytes).map_err(|_| KzgErrors::ParseError)?; + } + + if lines.next().is_some() { + return Err(KzgErrors::FileFormatError); + } + + Ok((g1_points, g2_points)) + } + *) + Definition parse_kzg_trusted_setup (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ trusted_setup ] => + ltac:(M.monadic + (let trusted_setup := M.alloc (| trusted_setup |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ lines := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "str", "lines", [] |), + [ M.read (| trusted_setup |) ] + |) + |) in + let~ n_g1 := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "usize"; + Ty.path "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::ParseIntError" ], + "map_err", + [ + Ty.path "revm_primitives::kzg::trusted_setup_points::KzgErrors"; + Ty.function + [ Ty.tuple [ Ty.path "core::num::error::ParseIntError" ] ] + (Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "str", + "parse", + [ Ty.path "usize" ] + |), + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "&") [ Ty.path "str" ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "str" ] ], + "ok_or", + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.path "core::str::iter::Lines", + [], + "next", + [] + |), + [ lines ] + |); + Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::FileFormatError" + [] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G1Points"; + Ty.path "alloc::alloc::Global" + ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G2Points"; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::ParseError" + [])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G1Points"; + Ty.path "alloc::alloc::Global" + ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G2Points"; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ n_g2 := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "usize"; + Ty.path "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "usize"; Ty.path "core::num::error::ParseIntError" ], + "map_err", + [ + Ty.path "revm_primitives::kzg::trusted_setup_points::KzgErrors"; + Ty.function + [ Ty.tuple [ Ty.path "core::num::error::ParseIntError" ] ] + (Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "str", + "parse", + [ Ty.path "usize" ] + |), + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "&") [ Ty.path "str" ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "str" ] ], + "ok_or", + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.path "core::str::iter::Lines", + [], + "next", + [] + |), + [ lines ] + |); + Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::FileFormatError" + [] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G1Points"; + Ty.path "alloc::alloc::Global" + ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G2Points"; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::ParseError" + [])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G1Points"; + Ty.path "alloc::alloc::Global" + ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G2Points"; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| n_g1 |)) + (M.read (| + M.get_constant (| + "revm_primitives::kzg::trusted_setup_points::NUM_G1_POINTS" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::MismatchedNumberOfPoints" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.ne + (M.read (| n_g2 |)) + (M.read (| + M.get_constant (| + "revm_primitives::kzg::trusted_setup_points::NUM_G2_POINTS" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::MismatchedNumberOfPoints" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ g1_points := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_primitives::kzg::trusted_setup_points::G1Points"; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "array") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] + ], + [], + "into_iter", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| g1_points |), + "revm_primitives::kzg::trusted_setup_points::G1Points", + 0 + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::IterMut") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let bytes := M.copy (| ฮณ0_0 |) in + let~ line := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "&") [ Ty.path "str" ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "str" ] + ], + "ok_or", + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.path "core::str::iter::Lines", + [], + "next", + [] + |), + [ lines ] + |); + Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::FileFormatError" + [] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G1Points"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G2Points"; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path "const_hex::error::FromHexError" + ], + "map_err", + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors"; + Ty.function + [ + Ty.tuple + [ + Ty.path + "const_hex::error::FromHexError" + ] + ] + (Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors") + ] + |), + [ + M.call_closure (| + M.get_function (| + "const_hex::decode_to_slice", + [ + Ty.apply + (Ty.path "&") + [ Ty.path "str" ] + ] + |), + [ + M.read (| line |); + (* Unsize *) + M.pointer_coercion (M.read (| bytes |)) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::ParseError" + [])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G1Points"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G2Points"; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ g2_points := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_primitives::kzg::trusted_setup_points::G2Points"; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "array") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ] + ], + [], + "into_iter", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| g2_points |), + "revm_primitives::kzg::trusted_setup_points::G2Points", + 0 + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::IterMut") + [ Ty.apply (Ty.path "array") [ Ty.path "u8" ] ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let bytes := M.copy (| ฮณ0_0 |) in + let~ line := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply (Ty.path "&") [ Ty.path "str" ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "str" ] + ], + "ok_or", + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.path "core::str::iter::Lines", + [], + "next", + [] + |), + [ lines ] + |); + Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::FileFormatError" + [] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G1Points"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G2Points"; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path "const_hex::error::FromHexError" + ], + "map_err", + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors"; + Ty.function + [ + Ty.tuple + [ + Ty.path + "const_hex::error::FromHexError" + ] + ] + (Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors") + ] + |), + [ + M.call_closure (| + M.get_function (| + "const_hex::decode_to_slice", + [ + Ty.apply + (Ty.path "&") + [ Ty.path "str" ] + ] + |), + [ + M.read (| line |); + (* Unsize *) + M.pointer_coercion (M.read (| bytes |)) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::ParseError" + [])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G1Points"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_primitives::kzg::trusted_setup_points::G2Points"; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.path + "revm_primitives::kzg::trusted_setup_points::KzgErrors" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "str" ] ], + "is_some", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.path "core::str::iter::Lines", + [], + "next", + [] + |), + [ lines ] + |) + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_primitives::kzg::trusted_setup_points::KzgErrors::FileFormatError" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ Value.Tuple [ M.read (| g1_points |); M.read (| g2_points |) ] ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_parse_kzg_trusted_setup : + M.IsFunction + "revm_primitives::kzg::trusted_setup_points::parse_kzg_trusted_setup" + parse_kzg_trusted_setup. + + (* + Enum KzgErrors + { + ty_params := []; + variants := + [ + { + name := "FailedCurrentDirectory"; + item := StructTuple []; + discriminant := None; + }; + { + name := "PathNotExists"; + item := StructTuple []; + discriminant := None; + }; + { + name := "IOError"; + item := StructTuple []; + discriminant := None; + }; + { + name := "NotValidFile"; + item := StructTuple []; + discriminant := None; + }; + { + name := "FileFormatError"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ParseError"; + item := StructTuple []; + discriminant := None; + }; + { + name := "MismatchedNumberOfPoints"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_kzg_trusted_setup_points_KzgErrors. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::KzgErrors". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::FailedCurrentDirectory" + |) in + M.alloc (| M.read (| Value.String "FailedCurrentDirectory" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::PathNotExists" + |) in + M.alloc (| M.read (| Value.String "PathNotExists" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::IOError" + |) in + M.alloc (| M.read (| Value.String "IOError" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::NotValidFile" + |) in + M.alloc (| M.read (| Value.String "NotValidFile" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::FileFormatError" + |) in + M.alloc (| M.read (| Value.String "FileFormatError" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::ParseError" + |) in + M.alloc (| M.read (| Value.String "ParseError" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::MismatchedNumberOfPoints" + |) in + M.alloc (| M.read (| Value.String "MismatchedNumberOfPoints" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_kzg_trusted_setup_points_KzgErrors. + + Module Impl_core_fmt_Display_for_revm_primitives_kzg_trusted_setup_points_KzgErrors. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::KzgErrors". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::FailedCurrentDirectory => "failed to get current directory", + Self::PathNotExists => "the specified path does not exist", + Self::IOError => "IO error", + Self::NotValidFile => "not a valid file", + Self::FileFormatError => "file is not properly formatted", + Self::ParseError => "could not parse as usize", + Self::MismatchedNumberOfPoints => "number of points does not match what is expected", + }; + f.write_str(s) + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ s := + M.copy (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::FailedCurrentDirectory" + |) in + Value.String "failed to get current directory")); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::PathNotExists" + |) in + M.alloc (| + M.read (| Value.String "the specified path does not exist" |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::IOError" + |) in + M.alloc (| M.read (| Value.String "IO error" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::NotValidFile" + |) in + M.alloc (| M.read (| Value.String "not a valid file" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::FileFormatError" + |) in + M.alloc (| + M.read (| Value.String "file is not properly formatted" |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::ParseError" + |) in + M.alloc (| M.read (| Value.String "could not parse as usize" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::kzg::trusted_setup_points::KzgErrors::MismatchedNumberOfPoints" + |) in + M.alloc (| + M.read (| + Value.String "number of points does not match what is expected" + |) + |))) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| s |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Display" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Display_for_revm_primitives_kzg_trusted_setup_points_KzgErrors. + + Module Impl_core_error_Error_for_revm_primitives_kzg_trusted_setup_points_KzgErrors. + Definition Self : Ty.t := Ty.path "revm_primitives::kzg::trusted_setup_points::KzgErrors". + + Axiom Implements : + M.IsTraitInstance + "core::error::Error" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_error_Error_for_revm_primitives_kzg_trusted_setup_points_KzgErrors. + End trusted_setup_points. +End kzg. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/precompile.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/precompile.md new file mode 100644 index 00000000..1f1587cc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/precompile.md @@ -0,0 +1,1778 @@ +# ๐Ÿ“ precompile.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/precompile.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module precompile. + Axiom PrecompileResult : + (Ty.path "revm_primitives::precompile::PrecompileResult") = + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ]). + + Axiom StandardPrecompileFn : + (Ty.path "revm_primitives::precompile::StandardPrecompileFn") = + (Ty.function + [ Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ]; Ty.path "u64" ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ])). + + Axiom EnvPrecompileFn : + (Ty.path "revm_primitives::precompile::EnvPrecompileFn") = + (Ty.function + [ + Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "u64"; + Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::Env" ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ])). + + (* Trait *) + (* Empty module 'StatefulPrecompile' *) + + (* Trait *) + (* Empty module 'StatefulPrecompileMut' *) + + Axiom StatefulPrecompileArc : + (Ty.path "revm_primitives::precompile::StatefulPrecompileArc") = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn [ ("revm_primitives::precompile::StatefulPrecompile::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom StatefulPrecompileBox : + (Ty.path "revm_primitives::precompile::StatefulPrecompileBox") = + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn [ ("revm_primitives::precompile::StatefulPrecompileMut::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ]). + + (* + Enum Precompile + { + ty_params := []; + variants := + [ + { + name := "Standard"; + item := + StructTuple + [ + Ty.function + [ + Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "u64" + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ]) + ]; + discriminant := None; + }; + { + name := "Env"; + item := + StructTuple + [ + Ty.function + [ + Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "u64"; + Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::Env" ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ]) + ]; + discriminant := None; + }; + { + name := "Stateful"; + item := + StructTuple + [ + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn [ ("revm_primitives::precompile::StatefulPrecompile::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ] + ]; + discriminant := None; + }; + { + name := "StatefulMut"; + item := + StructTuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn [ ("revm_primitives::precompile::StatefulPrecompileMut::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ] + ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_primitives_precompile_Precompile. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::Precompile". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::Standard", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::Precompile::Standard" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.function + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "u64" + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ]), + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::Env", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::Precompile::Env" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.function + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "u64"; + Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::Env" ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ]), + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::Stateful", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::Precompile::Stateful" + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("revm_primitives::precompile::StatefulPrecompile::Trait", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::StatefulMut", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::Precompile::StatefulMut" + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("revm_primitives::precompile::StatefulPrecompileMut::Trait", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_precompile_Precompile. + + Module Impl_core_convert_From_ref__alloy_primitives_bytes__Bytesu64Tocore_result_Result_Tuple_u64_alloy_primitives_bytes__Bytes__revm_primitives_precompile_PrecompileError_for_revm_primitives_precompile_Precompile. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::Precompile". + + (* + fn from(p: StandardPrecompileFn) -> Self { + Precompile::Standard(p) + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ p ] => + ltac:(M.monadic + (let p := M.alloc (| p |) in + Value.StructTuple "revm_primitives::precompile::Precompile::Standard" [ M.read (| p |) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ + (* T *) + Ty.function + [ Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ]; Ty.path "u64" ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ]) + ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_ref__alloy_primitives_bytes__Bytesu64Tocore_result_Result_Tuple_u64_alloy_primitives_bytes__Bytes__revm_primitives_precompile_PrecompileError_for_revm_primitives_precompile_Precompile. + + Module Impl_core_convert_From_ref__alloy_primitives_bytes__Bytesu64ref__revm_primitives_env_EnvTocore_result_Result_Tuple_u64_alloy_primitives_bytes__Bytes__revm_primitives_precompile_PrecompileError_for_revm_primitives_precompile_Precompile. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::Precompile". + + (* + fn from(p: EnvPrecompileFn) -> Self { + Precompile::Env(p) + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ p ] => + ltac:(M.monadic + (let p := M.alloc (| p |) in + Value.StructTuple "revm_primitives::precompile::Precompile::Env" [ M.read (| p |) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ + (* T *) + Ty.function + [ + Ty.apply (Ty.path "&") [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "u64"; + Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::Env" ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ]) + ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_ref__alloy_primitives_bytes__Bytesu64ref__revm_primitives_env_EnvTocore_result_Result_Tuple_u64_alloy_primitives_bytes__Bytes__revm_primitives_precompile_PrecompileError_for_revm_primitives_precompile_Precompile. + + Module Impl_core_convert_From_alloc_sync_Arc_Dyn_revm_primitives_precompile_StatefulPrecompile_Trait_alloc_alloc_Global_for_revm_primitives_precompile_Precompile. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::Precompile". + + (* + fn from(p: StatefulPrecompileArc) -> Self { + Precompile::Stateful(p) + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ p ] => + ltac:(M.monadic + (let p := M.alloc (| p |) in + Value.StructTuple + "revm_primitives::precompile::Precompile::Stateful" + [ (* Unsize *) M.pointer_coercion (M.read (| p |)) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ + (* T *) + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn [ ("revm_primitives::precompile::StatefulPrecompile::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ] + ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_alloc_sync_Arc_Dyn_revm_primitives_precompile_StatefulPrecompile_Trait_alloc_alloc_Global_for_revm_primitives_precompile_Precompile. + + Module Impl_core_convert_From_alloc_boxed_Box_Dyn_revm_primitives_precompile_StatefulPrecompileMut_Trait_alloc_alloc_Global_for_revm_primitives_precompile_Precompile. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::Precompile". + + (* + fn from(p: StatefulPrecompileBox) -> Self { + Precompile::StatefulMut(p) + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ p ] => + ltac:(M.monadic + (let p := M.alloc (| p |) in + Value.StructTuple + "revm_primitives::precompile::Precompile::StatefulMut" + [ (* Unsize *) M.pointer_coercion (M.read (| p |)) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ + (* T *) + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn [ ("revm_primitives::precompile::StatefulPrecompileMut::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ] + ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_alloc_boxed_Box_Dyn_revm_primitives_precompile_StatefulPrecompileMut_Trait_alloc_alloc_Global_for_revm_primitives_precompile_Precompile. + + Module Impl_core_fmt_Debug_for_revm_primitives_precompile_Precompile. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::Precompile". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Precompile::Standard(_) => f.write_str("Standard"), + Precompile::Env(_) => f.write_str("Env"), + Precompile::Stateful(_) => f.write_str("Stateful"), + Precompile::StatefulMut(_) => f.write_str("StatefulMut"), + } + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::Standard", + 0 + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Standard" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::Env", + 0 + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Env" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::Stateful", + 0 + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Stateful" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::StatefulMut", + 0 + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "StatefulMut" |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_precompile_Precompile. + + Module Impl_revm_primitives_precompile_Precompile. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::Precompile". + + (* + pub fn new_stateful(p: P) -> Self { + Self::Stateful(Arc::new(p)) + } + *) + Definition new_stateful (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ P ], [ p ] => + ltac:(M.monadic + (let p := M.alloc (| p |) in + Value.StructTuple + "revm_primitives::precompile::Precompile::Stateful" + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "alloc::sync::Arc") [ P; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [ M.read (| p |) ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_stateful : M.IsAssociatedFunction Self "new_stateful" new_stateful. + + (* + pub fn new_stateful_mut(p: P) -> Self { + Self::StatefulMut(Box::new(p)) + } + *) + Definition new_stateful_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ P ], [ p ] => + ltac:(M.monadic + (let p := M.alloc (| p |) in + Value.StructTuple + "revm_primitives::precompile::Precompile::StatefulMut" + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "alloc::boxed::Box") [ P; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [ M.read (| p |) ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_stateful_mut : + M.IsAssociatedFunction Self "new_stateful_mut" new_stateful_mut. + + (* + pub fn call(&mut self, bytes: &Bytes, gas_price: u64, env: &Env) -> PrecompileResult { + match self { + Precompile::Standard(p) => p(bytes, gas_price), + Precompile::Env(p) => p(bytes, gas_price, env), + Precompile::Stateful(p) => p.call(bytes, gas_price, env), + Precompile::StatefulMut(p) => p.call_mut(bytes, gas_price, env), + } + } + *) + Definition call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; bytes; gas_price; env ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let bytes := M.alloc (| bytes |) in + let gas_price := M.alloc (| gas_price |) in + let env := M.alloc (| env |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::Standard", + 0 + |) in + let p := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.read (| M.read (| p |) |), + [ M.read (| bytes |); M.read (| gas_price |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::Env", + 0 + |) in + let p := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.read (| M.read (| p |) |), + [ M.read (| bytes |); M.read (| gas_price |); M.read (| env |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::Stateful", + 0 + |) in + let p := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::precompile::StatefulPrecompile", + Ty.dyn [ ("revm_primitives::precompile::StatefulPrecompile::Trait", []) ], + [], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ ("revm_primitives::precompile::StatefulPrecompile::Trait", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ M.read (| p |) ] + |); + M.read (| bytes |); + M.read (| gas_price |); + M.read (| env |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::Precompile::StatefulMut", + 0 + |) in + let p := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::precompile::StatefulPrecompileMut", + Ty.dyn + [ ("revm_primitives::precompile::StatefulPrecompileMut::Trait", []) ], + [], + "call_mut", + [] + |), + [ + M.read (| M.read (| p |) |); + M.read (| bytes |); + M.read (| gas_price |); + M.read (| env |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_call : M.IsAssociatedFunction Self "call" call. + End Impl_revm_primitives_precompile_Precompile. + + (* + Enum PrecompileError + { + ty_params := []; + variants := + [ + { + name := "OutOfGas"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Blake2WrongLength"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Blake2WrongFinalIndicatorFlag"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ModexpExpOverflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ModexpBaseOverflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ModexpModOverflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Bn128FieldPointNotAMember"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Bn128AffineGFailedToCreate"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Bn128PairLength"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BlobInvalidInputLength"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BlobMismatchedVersion"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BlobVerifyKzgProofFailed"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Other"; + item := StructTuple [ Ty.path "alloc::string::String" ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::OutOfGas" + |) in + M.alloc (| + Value.StructTuple "revm_primitives::precompile::PrecompileError::OutOfGas" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Blake2WrongLength" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Blake2WrongLength" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Blake2WrongFinalIndicatorFlag" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Blake2WrongFinalIndicatorFlag" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::ModexpExpOverflow" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::ModexpExpOverflow" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::ModexpBaseOverflow" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::ModexpBaseOverflow" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::ModexpModOverflow" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::ModexpModOverflow" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Bn128FieldPointNotAMember" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Bn128FieldPointNotAMember" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Bn128AffineGFailedToCreate" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Bn128AffineGFailedToCreate" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Bn128PairLength" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Bn128PairLength" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::BlobInvalidInputLength" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::BlobInvalidInputLength" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::BlobMismatchedVersion" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::BlobMismatchedVersion" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::BlobVerifyKzgProofFailed" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::BlobVerifyKzgProofFailed" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Other", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Other" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloc::string::String", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_precompile_PrecompileError. + + Module Impl_core_fmt_Debug_for_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::OutOfGas" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "OutOfGas" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Blake2WrongLength" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Blake2WrongLength" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Blake2WrongFinalIndicatorFlag" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Blake2WrongFinalIndicatorFlag" |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::ModexpExpOverflow" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "ModexpExpOverflow" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::ModexpBaseOverflow" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "ModexpBaseOverflow" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::ModexpModOverflow" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "ModexpModOverflow" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Bn128FieldPointNotAMember" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Bn128FieldPointNotAMember" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Bn128AffineGFailedToCreate" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Bn128AffineGFailedToCreate" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Bn128PairLength" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Bn128PairLength" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::BlobInvalidInputLength" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "BlobInvalidInputLength" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::BlobMismatchedVersion" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "BlobMismatchedVersion" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::BlobVerifyKzgProofFailed" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "BlobVerifyKzgProofFailed" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Other", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Other" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_precompile_PrecompileError. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_precompile_PrecompileError. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::precompile::PrecompileError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::precompile::PrecompileError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::precompile::PrecompileError::Other", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::precompile::PrecompileError::Other", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloc::string::String", + [ Ty.path "alloc::string::String" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool true |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_precompile_PrecompileError. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_precompile_PrecompileError. + + Module Impl_core_cmp_Eq_for_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_precompile_PrecompileError. + + Module Impl_core_hash_Hash_for_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::precompile::PrecompileError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Other", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloc::string::String", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_precompile_PrecompileError. + + Module Impl_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + (* + pub fn other(err: impl Into) -> Self { + Self::Other(err.into()) + } + *) + Definition other (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ impl_Into_String_ ], [ err ] => + ltac:(M.monadic + (let err := M.alloc (| err |) in + Value.StructTuple + "revm_primitives::precompile::PrecompileError::Other" + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + impl_Into_String_, + [ Ty.path "alloc::string::String" ], + "into", + [] + |), + [ M.read (| err |) ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_other : M.IsAssociatedFunction Self "other" other. + End Impl_revm_primitives_precompile_PrecompileError. + + Module Impl_core_error_Error_for_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + Axiom Implements : + M.IsTraitInstance + "core::error::Error" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_error_Error_for_revm_primitives_precompile_PrecompileError. + + Module Impl_core_fmt_Display_for_revm_primitives_precompile_PrecompileError. + Definition Self : Ty.t := Ty.path "revm_primitives::precompile::PrecompileError". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::OutOfGas => "out of gas", + Self::Blake2WrongLength => "wrong input length for blake2", + Self::Blake2WrongFinalIndicatorFlag => "wrong final indicator flag for blake2", + Self::ModexpExpOverflow => "modexp exp overflow", + Self::ModexpBaseOverflow => "modexp base overflow", + Self::ModexpModOverflow => "modexp mod overflow", + Self::Bn128FieldPointNotAMember => "field point not a member of bn128 curve", + Self::Bn128AffineGFailedToCreate => "failed to create affine g point for bn128 curve", + Self::Bn128PairLength => "bn128 invalid pair length", + Self::BlobInvalidInputLength => "invalid blob input length", + Self::BlobMismatchedVersion => "mismatched blob version", + Self::BlobVerifyKzgProofFailed => "verifying blob kzg proof failed", + Self::Other(s) => s, + }; + f.write_str(s) + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ s := + M.copy (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::OutOfGas" + |) in + Value.String "out of gas")); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Blake2WrongLength" + |) in + M.alloc (| M.read (| Value.String "wrong input length for blake2" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Blake2WrongFinalIndicatorFlag" + |) in + M.alloc (| + M.read (| Value.String "wrong final indicator flag for blake2" |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::ModexpExpOverflow" + |) in + M.alloc (| M.read (| Value.String "modexp exp overflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::ModexpBaseOverflow" + |) in + M.alloc (| M.read (| Value.String "modexp base overflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::ModexpModOverflow" + |) in + M.alloc (| M.read (| Value.String "modexp mod overflow" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Bn128FieldPointNotAMember" + |) in + M.alloc (| + M.read (| Value.String "field point not a member of bn128 curve" |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Bn128AffineGFailedToCreate" + |) in + M.alloc (| + M.read (| + Value.String "failed to create affine g point for bn128 curve" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Bn128PairLength" + |) in + M.alloc (| M.read (| Value.String "bn128 invalid pair length" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::BlobInvalidInputLength" + |) in + M.alloc (| M.read (| Value.String "invalid blob input length" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::BlobMismatchedVersion" + |) in + M.alloc (| M.read (| Value.String "mismatched blob version" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::precompile::PrecompileError::BlobVerifyKzgProofFailed" + |) in + M.alloc (| M.read (| Value.String "verifying blob kzg proof failed" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::precompile::PrecompileError::Other", + 0 + |) in + let s := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloc::string::String", + [], + "deref", + [] + |), + [ M.read (| s |) ] + |) + |))) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| s |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Display" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Display_for_revm_primitives_precompile_PrecompileError. +End precompile. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/result.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/result.md new file mode 100644 index 00000000..2b5cb919 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/result.md @@ -0,0 +1,7767 @@ +# ๐Ÿ“ result.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/result.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module result. + Axiom EVMResult : + forall (DBError : Ty.t), + (Ty.apply (Ty.path "revm_primitives::result::EVMResult") [ DBError ]) = + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ] + ]). + + Axiom EVMResultGeneric : + forall (T DBError : Ty.t), + (Ty.apply (Ty.path "revm_primitives::result::EVMResultGeneric") [ T; DBError ]) = + (Ty.apply + (Ty.path "core::result::Result") + [ T; Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ] ]). + + (* StructRecord + { + name := "ResultAndState"; + ty_params := []; + fields := + [ + ("result", Ty.path "revm_primitives::result::ExecutionResult"); + ("state", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ]) + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_primitives_result_ResultAndState. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ResultAndState". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "ResultAndState" |); + M.read (| Value.String "result" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::result::ResultAndState", + "result" + |)); + M.read (| Value.String "state" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::result::ResultAndState", + "state" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_result_ResultAndState. + + Module Impl_core_clone_Clone_for_revm_primitives_result_ResultAndState. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ResultAndState". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::result::ResultAndState" + [ + ("result", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::result::ExecutionResult", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::result::ResultAndState", + "result" + |) + ] + |)); + ("state", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::result::ResultAndState", + "state" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_result_ResultAndState. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_ResultAndState. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ResultAndState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_ResultAndState. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_result_ResultAndState. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ResultAndState". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::result::ExecutionResult", + [ Ty.path "revm_primitives::result::ExecutionResult" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::result::ResultAndState", + "result" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::result::ResultAndState", + "result" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::result::ResultAndState", + "state" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::result::ResultAndState", + "state" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_result_ResultAndState. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_result_ResultAndState. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ResultAndState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_result_ResultAndState. + + Module Impl_core_cmp_Eq_for_revm_primitives_result_ResultAndState. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ResultAndState". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_result_ResultAndState. + + (* + Enum ExecutionResult + { + ty_params := []; + variants := + [ + { + name := "Success"; + item := + StructRecord + [ + ("reason", Ty.path "revm_primitives::result::SuccessReason"); + ("gas_used", Ty.path "u64"); + ("gas_refunded", Ty.path "u64"); + ("logs", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ]); + ("output", Ty.path "revm_primitives::result::Output") + ]; + discriminant := None; + }; + { + name := "Revert"; + item := + StructRecord + [ ("gas_used", Ty.path "u64"); ("output", Ty.path "alloy_primitives::bytes_::Bytes") + ]; + discriminant := None; + }; + { + name := "Halt"; + item := + StructRecord + [ + ("reason", Ty.path "revm_primitives::result::HaltReason"); + ("gas_used", Ty.path "u64") + ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_result_ExecutionResult. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ExecutionResult". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "reason" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "gas_used" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "gas_refunded" + |) in + let ฮณ1_3 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "logs" + |) in + let ฮณ1_4 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "output" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + let __self_3 := M.alloc (| ฮณ1_3 |) in + let __self_4 := M.alloc (| ฮณ1_4 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field5_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Success" |); + M.read (| Value.String "reason" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "gas_used" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_1 |)); + M.read (| Value.String "gas_refunded" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_2 |)); + M.read (| Value.String "logs" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_3 |)); + M.read (| Value.String "output" |); + (* Unsize *) M.pointer_coercion __self_4 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Revert", + "gas_used" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Revert", + "output" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Revert" |); + M.read (| Value.String "gas_used" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "output" |); + (* Unsize *) M.pointer_coercion __self_1 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Halt", + "reason" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Halt", + "gas_used" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Halt" |); + M.read (| Value.String "reason" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "gas_used" |); + (* Unsize *) M.pointer_coercion __self_1 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_result_ExecutionResult. + + Module Impl_core_clone_Clone_for_revm_primitives_result_ExecutionResult. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ExecutionResult". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "reason" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "gas_used" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "gas_refunded" + |) in + let ฮณ1_3 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "logs" + |) in + let ฮณ1_4 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "output" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + let __self_3 := M.alloc (| ฮณ1_3 |) in + let __self_4 := M.alloc (| ฮณ1_4 |) in + M.alloc (| + Value.StructRecord + "revm_primitives::result::ExecutionResult::Success" + [ + ("reason", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::result::SuccessReason", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("gas_used", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "u64", + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)); + ("gas_refunded", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "u64", + [], + "clone", + [] + |), + [ M.read (| __self_2 |) ] + |)); + ("logs", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ M.read (| __self_3 |) ] + |)); + ("output", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::result::Output", + [], + "clone", + [] + |), + [ M.read (| __self_4 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Revert", + "gas_used" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Revert", + "output" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + Value.StructRecord + "revm_primitives::result::ExecutionResult::Revert" + [ + ("gas_used", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "u64", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("output", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Halt", + "reason" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Halt", + "gas_used" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + Value.StructRecord + "revm_primitives::result::ExecutionResult::Halt" + [ + ("reason", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::result::HaltReason", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("gas_used", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "u64", + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_result_ExecutionResult. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_ExecutionResult. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ExecutionResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_ExecutionResult. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_result_ExecutionResult. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ExecutionResult". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::ExecutionResult" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::ExecutionResult" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::ExecutionResult::Success", + "reason" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::ExecutionResult::Success", + "gas_used" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::ExecutionResult::Success", + "gas_refunded" + |) in + let ฮณ2_3 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::ExecutionResult::Success", + "logs" + |) in + let ฮณ2_4 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::ExecutionResult::Success", + "output" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let __self_2 := M.alloc (| ฮณ2_2 |) in + let __self_3 := M.alloc (| ฮณ2_3 |) in + let __self_4 := M.alloc (| ฮณ2_4 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::ExecutionResult::Success", + "reason" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::ExecutionResult::Success", + "gas_used" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::ExecutionResult::Success", + "gas_refunded" + |) in + let ฮณ2_3 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::ExecutionResult::Success", + "logs" + |) in + let ฮณ2_4 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::ExecutionResult::Success", + "output" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + let __arg1_2 := M.alloc (| ฮณ2_2 |) in + let __arg1_3 := M.alloc (| ฮณ2_3 |) in + let __arg1_4 := M.alloc (| ฮณ2_4 |) in + M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::result::SuccessReason", + [ Ty.path "revm_primitives::result::SuccessReason" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| M.read (| __self_1 |) |)) + (M.read (| M.read (| __arg1_1 |) |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| M.read (| __self_2 |) |)) + (M.read (| M.read (| __arg1_2 |) |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ M.read (| __self_3 |); M.read (| __arg1_3 |) ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::result::Output", + [ Ty.path "revm_primitives::result::Output" ], + "eq", + [] + |), + [ M.read (| __self_4 |); M.read (| __arg1_4 |) ] + |))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::ExecutionResult::Revert", + "gas_used" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::ExecutionResult::Revert", + "output" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::ExecutionResult::Revert", + "gas_used" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::ExecutionResult::Revert", + "output" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| M.read (| __self_0 |) |)) + (M.read (| M.read (| __arg1_0 |) |)), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ M.read (| __self_1 |); M.read (| __arg1_1 |) ] + |))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::ExecutionResult::Halt", + "reason" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::ExecutionResult::Halt", + "gas_used" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::ExecutionResult::Halt", + "reason" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::ExecutionResult::Halt", + "gas_used" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::result::HaltReason", + [ Ty.path "revm_primitives::result::HaltReason" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| M.read (| __self_1 |) |)) + (M.read (| M.read (| __arg1_1 |) |)))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::intrinsics::unreachable", [] |), + [] + |) + |) + |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_result_ExecutionResult. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_result_ExecutionResult. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ExecutionResult". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_result_ExecutionResult. + + Module Impl_core_cmp_Eq_for_revm_primitives_result_ExecutionResult. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ExecutionResult". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_result_ExecutionResult. + + Module Impl_core_hash_Hash_for_revm_primitives_result_ExecutionResult. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ExecutionResult". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::ExecutionResult" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "reason" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "gas_used" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "gas_refunded" + |) in + let ฮณ1_3 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "logs" + |) in + let ฮณ1_4 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "output" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + let __self_3 := M.alloc (| ฮณ1_3 |) in + let __self_4 := M.alloc (| ฮณ1_4 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::result::SuccessReason", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u64", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u64", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_2 |); M.read (| state |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "hash", + [ __H ] + |), + [ M.read (| __self_3 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::result::Output", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_4 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Revert", + "gas_used" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Revert", + "output" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u64", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Halt", + "reason" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Halt", + "gas_used" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::result::HaltReason", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u64", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_result_ExecutionResult. + + Module Impl_revm_primitives_result_ExecutionResult. + Definition Self : Ty.t := Ty.path "revm_primitives::result::ExecutionResult". + + (* + pub fn is_success(&self) -> bool { + matches!(self, Self::Success { .. }) + } + *) + Definition is_success (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_success : M.IsAssociatedFunction Self "is_success" is_success. + + (* + pub fn is_halt(&self) -> bool { + matches!(self, Self::Halt { .. }) + } + *) + Definition is_halt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::result::ExecutionResult::Halt" |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_halt : M.IsAssociatedFunction Self "is_halt" is_halt. + + (* + pub fn output(&self) -> Option<&Bytes> { + match self { + Self::Success { output, .. } => Some(output.data()), + Self::Revert { output, .. } => Some(output), + _ => None, + } + } + *) + Definition output (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "output" + |) in + let output := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::result::Output", + "data", + [] + |), + [ M.read (| output |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Revert", + "output" + |) in + let output := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| output |) ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_output : M.IsAssociatedFunction Self "output" output. + + (* + pub fn into_output(self) -> Option { + match self { + Self::Success { output, .. } => Some(output.into_data()), + Self::Revert { output, .. } => Some(output), + _ => None, + } + } + *) + Definition into_output (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "output" + |) in + let output := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::result::Output", + "into_data", + [] + |), + [ M.read (| output |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Revert", + "output" + |) in + let output := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| output |) ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_output : M.IsAssociatedFunction Self "into_output" into_output. + + (* + pub fn logs(&self) -> &[Log] { + match self { + Self::Success { logs, .. } => logs, + _ => &[], + } + } + *) + Definition logs (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "logs" + |) in + let logs := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ M.read (| logs |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| (* Unsize *) M.pointer_coercion (M.alloc (| Value.Array [] |)) |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_logs : M.IsAssociatedFunction Self "logs" logs. + + (* + pub fn into_logs(self) -> Vec { + match self { + Self::Success { logs, .. } => logs, + _ => Vec::new(), + } + } + *) + Definition into_logs (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "logs" + |) in + let logs := M.copy (| ฮณ0_0 |) in + logs)); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_logs : M.IsAssociatedFunction Self "into_logs" into_logs. + + (* + pub fn gas_used(&self) -> u64 { + match *self { + Self::Success { gas_used, .. } + | Self::Revert { gas_used, .. } + | Self::Halt { gas_used, .. } => gas_used, + } + } + *) + Definition gas_used (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.read (| self |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Success", + "gas_used" + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + Value.Tuple [ gas_used ])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Revert", + "gas_used" + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + Value.Tuple [ gas_used ])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ExecutionResult::Halt", + "gas_used" + |) in + let gas_used := M.copy (| ฮณ0_0 |) in + Value.Tuple [ gas_used ])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with | [ gas_used ] => gas_used | _ => M.impossible (||) end)) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_gas_used : M.IsAssociatedFunction Self "gas_used" gas_used. + End Impl_revm_primitives_result_ExecutionResult. + + (* + Enum Output + { + ty_params := []; + variants := + [ + { + name := "Call"; + item := StructTuple [ Ty.path "alloy_primitives::bytes_::Bytes" ]; + discriminant := None; + }; + { + name := "Create"; + item := + StructTuple + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ] + ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_result_Output. + Definition Self : Ty.t := Ty.path "revm_primitives::result::Output". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Call", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Call" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 1 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Create" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + (* Unsize *) M.pointer_coercion __self_1 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_result_Output. + + Module Impl_core_clone_Clone_for_revm_primitives_result_Output. + Definition Self : Ty.t := Ty.path "revm_primitives::result::Output". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Call", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::Output::Call" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 1 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::Output::Create" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ], + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_result_Output. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_Output. + Definition Self : Ty.t := Ty.path "revm_primitives::result::Output". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_Output. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_result_Output. + Definition Self : Ty.t := Ty.path "revm_primitives::result::Output". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::Output" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::Output" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::result::Output::Call", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::result::Output::Call", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::result::Output::Create", + 0 + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::result::Output::Create", + 1 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::result::Output::Create", + 0 + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::result::Output::Create", + 1 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bytes_::Bytes", + [ Ty.path "alloy_primitives::bytes_::Bytes" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ] + ], + "eq", + [] + |), + [ M.read (| __self_1 |); M.read (| __arg1_1 |) ] + |))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::intrinsics::unreachable", [] |), + [] + |) + |) + |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_result_Output. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_result_Output. + Definition Self : Ty.t := Ty.path "revm_primitives::result::Output". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_result_Output. + + Module Impl_core_cmp_Eq_for_revm_primitives_result_Output. + Definition Self : Ty.t := Ty.path "revm_primitives::result::Output". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_result_Output. + + Module Impl_core_hash_Hash_for_revm_primitives_result_Output. + Definition Self : Ty.t := Ty.path "revm_primitives::result::Output". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::Output" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Call", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 1 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ], + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_result_Output. + + Module Impl_revm_primitives_result_Output. + Definition Self : Ty.t := Ty.path "revm_primitives::result::Output". + + (* + pub fn into_data(self) -> Bytes { + match self { + Output::Call(data) => data, + Output::Create(data, _) => data, + } + } + *) + Definition into_data (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Call", + 0 + |) in + let data := M.copy (| ฮณ0_0 |) in + data)); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 1 + |) in + let data := M.copy (| ฮณ0_0 |) in + data)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_data : M.IsAssociatedFunction Self "into_data" into_data. + + (* + pub fn data(&self) -> &Bytes { + match self { + Output::Call(data) => data, + Output::Create(data, _) => data, + } + } + *) + Definition data (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Call", + 0 + |) in + let data := M.alloc (| ฮณ1_0 |) in + M.alloc (| M.read (| data |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 1 + |) in + let data := M.alloc (| ฮณ1_0 |) in + M.alloc (| M.read (| data |) |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_data : M.IsAssociatedFunction Self "data" data. + + (* + pub fn address(&self) -> Option<&Address> { + match self { + Output::Call(_) => None, + Output::Create(_, address) => address.as_ref(), + } + } + *) + Definition address (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Call", + 0 + |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::Output::Create", + 1 + |) in + let address := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::address::Address" ], + "as_ref", + [] + |), + [ M.read (| address |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_address : M.IsAssociatedFunction Self "address" address. + End Impl_revm_primitives_result_Output. + + (* + Enum EVMError + { + ty_params := [ "DBError" ]; + variants := + [ + { + name := "Transaction"; + item := StructTuple [ Ty.path "revm_primitives::result::InvalidTransaction" ]; + discriminant := None; + }; + { + name := "Header"; + item := StructTuple [ Ty.path "revm_primitives::result::InvalidHeader" ]; + discriminant := None; + }; + { + name := "Database"; + item := StructTuple [ DBError ]; + discriminant := None; + }; + { + name := "Custom"; + item := StructTuple [ Ty.path "alloc::string::String" ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_where_core_fmt_Debug_DBError_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + (* Debug *) + Definition fmt (DBError : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DBError in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Transaction", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Transaction" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Header", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Header" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Database", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Database" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Custom", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Custom" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self DBError) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt DBError)) ]. + End Impl_core_fmt_Debug_where_core_fmt_Debug_DBError_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_clone_Clone_where_core_clone_Clone_DBError_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + (* Clone *) + Definition clone (DBError : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DBError in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Transaction", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::EVMError::Transaction" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::result::InvalidTransaction", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Header", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::EVMError::Header" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::result::InvalidHeader", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Database", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::EVMError::Database" + [ + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", DBError, [], "clone", [] |), + [ M.read (| __self_0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Custom", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::EVMError::Custom" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloc::string::String", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self DBError) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone DBError)) ]. + End Impl_core_clone_Clone_where_core_clone_Clone_DBError_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::marker::StructuralPartialEq" + (Self DBError) + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_cmp_PartialEq_where_core_cmp_PartialEq_DBError_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + (* PartialEq *) + Definition eq (DBError : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DBError in + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ] ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ] ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::result::EVMError::Transaction", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::result::EVMError::Transaction", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::result::InvalidTransaction", + [ Ty.path "revm_primitives::result::InvalidTransaction" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::result::EVMError::Header", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::result::EVMError::Header", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::result::InvalidHeader", + [ Ty.path "revm_primitives::result::InvalidHeader" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::result::EVMError::Database", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::result::EVMError::Database", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + DBError, + [ DBError ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::result::EVMError::Custom", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::result::EVMError::Custom", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloc::string::String", + [ Ty.path "alloc::string::String" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::intrinsics::unreachable", [] |), + [] + |) + |) + |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::cmp::PartialEq" + (Self DBError) + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method (eq DBError)) ]. + End Impl_core_cmp_PartialEq_where_core_cmp_PartialEq_DBError_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::marker::StructuralEq" + (Self DBError) + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_cmp_Eq_where_core_cmp_Eq_DBError_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + (* Eq *) + Definition assert_receiver_is_total_eq + (DBError : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self DBError in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::cmp::Eq" + (Self DBError) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("assert_receiver_is_total_eq", + InstanceField.Method (assert_receiver_is_total_eq DBError)) + ]. + End Impl_core_cmp_Eq_where_core_cmp_Eq_DBError_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_hash_Hash_where_core_hash_Hash_DBError_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + (* Hash *) + Definition hash (DBError : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DBError in + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ] ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Transaction", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::result::InvalidTransaction", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Header", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::result::InvalidHeader", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Database", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", DBError, [], "hash", [ __H ] |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Custom", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloc::string::String", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::hash::Hash" + (Self DBError) + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method (hash DBError)) ]. + End Impl_core_hash_Hash_where_core_hash_Hash_DBError_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_error_Error_where_core_error_Error_DBError_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + (* + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Transaction(e) => Some(e), + Self::Header(e) => Some(e), + Self::Database(e) => Some(e), + Self::Custom(_) => None, + } + } + *) + Definition source (DBError : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DBError in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Transaction", + 0 + |) in + let e := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ (* Unsize *) M.pointer_coercion (M.read (| e |)) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Header", + 0 + |) in + let e := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ (* Unsize *) M.pointer_coercion (M.read (| e |)) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Database", + 0 + |) in + let e := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ (* Unsize *) M.pointer_coercion (M.read (| e |)) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Custom", + 0 + |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::error::Error" + (Self DBError) + (* Trait polymorphic types *) [] + (* Instance *) [ ("source", InstanceField.Method (source DBError)) ]. + End Impl_core_error_Error_where_core_error_Error_DBError_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_fmt_Display_where_core_fmt_Display_DBError_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Transaction(e) => write!(f, "transaction validation error: {e}"), + Self::Header(e) => write!(f, "header validation error: {e}"), + Self::Database(e) => write!(f, "database error: {e}"), + Self::Custom(e) => f.write_str(e), + } + } + *) + Definition fmt (DBError : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DBError in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Transaction", + 0 + |) in + let e := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "transaction validation error: " |) ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::result::InvalidTransaction" + ] + ] + |), + [ e ] + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Header", + 0 + |) in + let e := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "header validation error: " |) ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::result::InvalidHeader" ] + ] + |), + [ e ] + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Database", + 0 + |) in + let e := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array [ M.read (| Value.String "database error: " |) ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.apply (Ty.path "&") [ DBError ] ] + |), + [ e ] + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::EVMError::Custom", + 0 + |) in + let e := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloc::string::String", + [], + "deref", + [] + |), + [ M.read (| e |) ] + |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::fmt::Display" + (Self DBError) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt DBError)) ]. + End Impl_core_fmt_Display_where_core_fmt_Display_DBError_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_convert_From_revm_primitives_result_InvalidTransaction_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + (* + fn from(value: InvalidTransaction) -> Self { + Self::Transaction(value) + } + *) + Definition from (DBError : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DBError in + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + Value.StructTuple + "revm_primitives::result::EVMError::Transaction" + [ M.read (| value |) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::convert::From" + (Self DBError) + (* Trait polymorphic types *) + [ (* T *) Ty.path "revm_primitives::result::InvalidTransaction" ] + (* Instance *) [ ("from", InstanceField.Method (from DBError)) ]. + End Impl_core_convert_From_revm_primitives_result_InvalidTransaction_for_revm_primitives_result_EVMError_DBError. + + Module Impl_core_convert_From_revm_primitives_result_InvalidHeader_for_revm_primitives_result_EVMError_DBError. + Definition Self (DBError : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ DBError ]. + + (* + fn from(value: InvalidHeader) -> Self { + Self::Header(value) + } + *) + Definition from (DBError : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DBError in + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + Value.StructTuple "revm_primitives::result::EVMError::Header" [ M.read (| value |) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DBError : Ty.t), + M.IsTraitInstance + "core::convert::From" + (Self DBError) + (* Trait polymorphic types *) [ (* T *) Ty.path "revm_primitives::result::InvalidHeader" ] + (* Instance *) [ ("from", InstanceField.Method (from DBError)) ]. + End Impl_core_convert_From_revm_primitives_result_InvalidHeader_for_revm_primitives_result_EVMError_DBError. + + (* + Enum InvalidTransaction + { + ty_params := []; + variants := + [ + { + name := "PriorityFeeGreaterThanMaxFee"; + item := StructTuple []; + discriminant := None; + }; + { + name := "GasPriceLessThanBasefee"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CallerGasLimitMoreThanBlock"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CallGasCostMoreThanGasLimit"; + item := StructTuple []; + discriminant := None; + }; + { + name := "RejectCallerWithCode"; + item := StructTuple []; + discriminant := None; + }; + { + name := "LackOfFundForMaxFee"; + item := + StructRecord + [ + ("fee", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ]); + ("balance", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ]) + ]; + discriminant := None; + }; + { + name := "OverflowPaymentInTransaction"; + item := StructTuple []; + discriminant := None; + }; + { + name := "NonceOverflowInTransaction"; + item := StructTuple []; + discriminant := None; + }; + { + name := "NonceTooHigh"; + item := StructRecord [ ("tx", Ty.path "u64"); ("state", Ty.path "u64") ]; + discriminant := None; + }; + { + name := "NonceTooLow"; + item := StructRecord [ ("tx", Ty.path "u64"); ("state", Ty.path "u64") ]; + discriminant := None; + }; + { + name := "CreateInitCodeSizeLimit"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidChainId"; + item := StructTuple []; + discriminant := None; + }; + { + name := "AccessListNotSupported"; + item := StructTuple []; + discriminant := None; + }; + { + name := "MaxFeePerBlobGasNotSupported"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BlobVersionedHashesNotSupported"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BlobGasPriceGreaterThanMax"; + item := StructTuple []; + discriminant := None; + }; + { + name := "EmptyBlobs"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BlobCreateTransaction"; + item := StructTuple []; + discriminant := None; + }; + { + name := "TooManyBlobs"; + item := StructTuple []; + discriminant := None; + }; + { + name := "BlobVersionNotSupported"; + item := StructTuple []; + discriminant := None; + }; + { + name := "EofInitcodesNotSupported"; + item := StructTuple []; + discriminant := None; + }; + { + name := "EofInitcodesNumberLimit"; + item := StructTuple []; + discriminant := None; + }; + { + name := "EofInitcodesSizeLimit"; + item := StructTuple []; + discriminant := None; + }; + { + name := "EofCrateShouldHaveToAddress"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_result_InvalidTransaction. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidTransaction". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::PriorityFeeGreaterThanMaxFee" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "PriorityFeeGreaterThanMaxFee" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::GasPriceLessThanBasefee" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "GasPriceLessThanBasefee" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::CallerGasLimitMoreThanBlock" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "CallerGasLimitMoreThanBlock" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::CallGasCostMoreThanGasLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "CallGasCostMoreThanGasLimit" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::RejectCallerWithCode" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "RejectCallerWithCode" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "fee" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "balance" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "LackOfFundForMaxFee" |); + M.read (| Value.String "fee" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "balance" |); + (* Unsize *) M.pointer_coercion __self_1 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::OverflowPaymentInTransaction" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "OverflowPaymentInTransaction" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceOverflowInTransaction" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "NonceOverflowInTransaction" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "tx" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "state" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "NonceTooHigh" |); + M.read (| Value.String "tx" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "state" |); + (* Unsize *) M.pointer_coercion __self_1 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "tx" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "state" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "NonceTooLow" |); + M.read (| Value.String "tx" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "state" |); + (* Unsize *) M.pointer_coercion __self_1 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::CreateInitCodeSizeLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "CreateInitCodeSizeLimit" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::InvalidChainId" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "InvalidChainId" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::AccessListNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "AccessListNotSupported" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::MaxFeePerBlobGasNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "MaxFeePerBlobGasNotSupported" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobVersionedHashesNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "BlobVersionedHashesNotSupported" |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobGasPriceGreaterThanMax" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "BlobGasPriceGreaterThanMax" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EmptyBlobs" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "EmptyBlobs" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobCreateTransaction" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "BlobCreateTransaction" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::TooManyBlobs" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "TooManyBlobs" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobVersionNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "BlobVersionNotSupported" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofInitcodesNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "EofInitcodesNotSupported" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofInitcodesNumberLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "EofInitcodesNumberLimit" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofInitcodesSizeLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "EofInitcodesSizeLimit" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofCrateShouldHaveToAddress" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "EofCrateShouldHaveToAddress" |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_result_InvalidTransaction. + + Module Impl_core_clone_Clone_for_revm_primitives_result_InvalidTransaction. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidTransaction". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::PriorityFeeGreaterThanMaxFee" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::PriorityFeeGreaterThanMaxFee" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::GasPriceLessThanBasefee" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::GasPriceLessThanBasefee" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::CallerGasLimitMoreThanBlock" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::CallerGasLimitMoreThanBlock" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::CallGasCostMoreThanGasLimit" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::CallGasCostMoreThanGasLimit" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::RejectCallerWithCode" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::RejectCallerWithCode" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "fee" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "balance" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + Value.StructRecord + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee" + [ + ("fee", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("balance", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::OverflowPaymentInTransaction" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::OverflowPaymentInTransaction" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceOverflowInTransaction" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::NonceOverflowInTransaction" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "tx" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "state" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + Value.StructRecord + "revm_primitives::result::InvalidTransaction::NonceTooHigh" + [ + ("tx", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "u64", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("state", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "u64", + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "tx" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "state" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + M.alloc (| + Value.StructRecord + "revm_primitives::result::InvalidTransaction::NonceTooLow" + [ + ("tx", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "u64", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("state", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "u64", + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::CreateInitCodeSizeLimit" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::CreateInitCodeSizeLimit" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::InvalidChainId" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::InvalidChainId" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::AccessListNotSupported" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::AccessListNotSupported" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::MaxFeePerBlobGasNotSupported" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::MaxFeePerBlobGasNotSupported" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobVersionedHashesNotSupported" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::BlobVersionedHashesNotSupported" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobGasPriceGreaterThanMax" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::BlobGasPriceGreaterThanMax" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EmptyBlobs" + |) in + M.alloc (| + Value.StructTuple "revm_primitives::result::InvalidTransaction::EmptyBlobs" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobCreateTransaction" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::BlobCreateTransaction" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::TooManyBlobs" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::TooManyBlobs" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobVersionNotSupported" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::BlobVersionNotSupported" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofInitcodesNotSupported" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::EofInitcodesNotSupported" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofInitcodesNumberLimit" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::EofInitcodesNumberLimit" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofInitcodesSizeLimit" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::EofInitcodesSizeLimit" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofCrateShouldHaveToAddress" + |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::InvalidTransaction::EofCrateShouldHaveToAddress" + [] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_result_InvalidTransaction. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_InvalidTransaction. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidTransaction". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_InvalidTransaction. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_result_InvalidTransaction. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidTransaction". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::InvalidTransaction" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::InvalidTransaction" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "fee" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "balance" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "fee" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "balance" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ], + "eq", + [] + |), + [ M.read (| __self_1 |); M.read (| __arg1_1 |) ] + |))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "tx" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "state" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "tx" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "state" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| M.read (| __self_0 |) |)) + (M.read (| M.read (| __arg1_0 |) |)), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| M.read (| __self_1 |) |)) + (M.read (| M.read (| __arg1_1 |) |)))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "tx" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "state" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "tx" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "state" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| M.read (| __self_0 |) |)) + (M.read (| M.read (| __arg1_0 |) |)), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| M.read (| __self_1 |) |)) + (M.read (| M.read (| __arg1_1 |) |)))) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool true |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_result_InvalidTransaction. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_result_InvalidTransaction. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidTransaction". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_result_InvalidTransaction. + + Module Impl_core_cmp_Eq_for_revm_primitives_result_InvalidTransaction. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidTransaction". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_result_InvalidTransaction. + + Module Impl_core_hash_Hash_for_revm_primitives_result_InvalidTransaction. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidTransaction". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::InvalidTransaction" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "fee" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "balance" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ], + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "tx" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "state" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u64", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u64", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "tx" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "state" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u64", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "u64", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_result_InvalidTransaction. + + Module Impl_core_error_Error_for_revm_primitives_result_InvalidTransaction. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidTransaction". + + Axiom Implements : + M.IsTraitInstance + "core::error::Error" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_error_Error_for_revm_primitives_result_InvalidTransaction. + + Module Impl_core_fmt_Display_for_revm_primitives_result_InvalidTransaction. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidTransaction". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::PriorityFeeGreaterThanMaxFee => { + write!(f, "priority fee is greater than max fee") + } + Self::GasPriceLessThanBasefee => { + write!(f, "gas price is less than basefee") + } + Self::CallerGasLimitMoreThanBlock => { + write!(f, "caller gas limit exceeds the block gas limit") + } + Self::CallGasCostMoreThanGasLimit => { + write!(f, "call gas cost exceeds the gas limit") + } + Self::RejectCallerWithCode => { + write!(f, "reject transactions from senders with deployed code") + } + Self::LackOfFundForMaxFee { fee, balance } => { + write!(f, "lack of funds ({balance}) for max fee ({fee})") + } + Self::OverflowPaymentInTransaction => { + write!(f, "overflow payment in transaction") + } + Self::NonceOverflowInTransaction => { + write!(f, "nonce overflow in transaction") + } + Self::NonceTooHigh { tx, state } => { + write!(f, "nonce {tx} too high, expected {state}") + } + Self::NonceTooLow { tx, state } => { + write!(f, "nonce {tx} too low, expected {state}") + } + Self::CreateInitCodeSizeLimit => { + write!(f, "create initcode size limit") + } + Self::InvalidChainId => write!(f, "invalid chain ID"), + Self::AccessListNotSupported => write!(f, "access list not supported"), + Self::MaxFeePerBlobGasNotSupported => { + write!(f, "max fee per blob gas not supported") + } + Self::BlobVersionedHashesNotSupported => { + write!(f, "blob versioned hashes not supported") + } + Self::BlobGasPriceGreaterThanMax => { + write!(f, "blob gas price is greater than max fee per blob gas") + } + Self::EmptyBlobs => write!(f, "empty blobs"), + Self::BlobCreateTransaction => write!(f, "blob create transaction"), + Self::TooManyBlobs => write!(f, "too many blobs"), + Self::BlobVersionNotSupported => write!(f, "blob version not supported"), + Self::EofInitcodesNotSupported => write!(f, "EOF initcodes not supported"), + Self::EofCrateShouldHaveToAddress => write!(f, "EOF crate should have `to` address"), + Self::EofInitcodesSizeLimit => write!(f, "EOF initcodes size limit"), + Self::EofInitcodesNumberLimit => write!(f, "EOF initcodes number limit"), + #[cfg(feature = "optimism")] + Self::DepositSystemTxPostRegolith => { + write!( + f, + "deposit system transactions post regolith hardfork are not supported" + ) + } + #[cfg(feature = "optimism")] + Self::HaltedDepositPostRegolith => { + write!( + f, + "deposit transaction halted post-regolith; error will be bubbled up to main return handler" + ) + } + } + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::PriorityFeeGreaterThanMaxFee" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "priority fee is greater than max fee" + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::GasPriceLessThanBasefee" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "gas price is less than basefee" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::CallerGasLimitMoreThanBlock" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "caller gas limit exceeds the block gas limit" + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::CallGasCostMoreThanGasLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "call gas cost exceeds the gas limit" + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::RejectCallerWithCode" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "reject transactions from senders with deployed code" + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "fee" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::LackOfFundForMaxFee", + "balance" + |) in + let fee := M.alloc (| ฮณ1_0 |) in + let balance := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| Value.String "lack of funds (" |); + M.read (| Value.String ") for max fee (" |); + M.read (| Value.String ")" |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ] + ] + ] + |), + [ balance ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ] + ] + ] + |), + [ fee ] + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::OverflowPaymentInTransaction" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "overflow payment in transaction" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceOverflowInTransaction" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "nonce overflow in transaction" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "tx" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooHigh", + "state" + |) in + let tx := M.alloc (| ฮณ1_0 |) in + let state := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| Value.String "nonce " |); + M.read (| Value.String " too high, expected " |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.apply (Ty.path "&") [ Ty.path "u64" ] ] + |), + [ tx ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.apply (Ty.path "&") [ Ty.path "u64" ] ] + |), + [ state ] + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "tx" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::InvalidTransaction::NonceTooLow", + "state" + |) in + let tx := M.alloc (| ฮณ1_0 |) in + let state := M.alloc (| ฮณ1_1 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| Value.String "nonce " |); + M.read (| Value.String " too low, expected " |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.apply (Ty.path "&") [ Ty.path "u64" ] ] + |), + [ tx ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.apply (Ty.path "&") [ Ty.path "u64" ] ] + |), + [ state ] + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::CreateInitCodeSizeLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "create initcode size limit" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::InvalidChainId" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array [ M.read (| Value.String "invalid chain ID" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::AccessListNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "access list not supported" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::MaxFeePerBlobGasNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "max fee per blob gas not supported" |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobVersionedHashesNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "blob versioned hashes not supported" + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobGasPriceGreaterThanMax" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "blob gas price is greater than max fee per blob gas" + |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EmptyBlobs" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array [ M.read (| Value.String "empty blobs" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobCreateTransaction" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "blob create transaction" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::TooManyBlobs" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array [ M.read (| Value.String "too many blobs" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::BlobVersionNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "blob version not supported" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofInitcodesNotSupported" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "EOF initcodes not supported" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofCrateShouldHaveToAddress" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "EOF crate should have `to` address" |) + ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofInitcodesSizeLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "EOF initcodes size limit" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidTransaction::EofInitcodesNumberLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "EOF initcodes number limit" |) ] + |)) + ] + |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Display" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Display_for_revm_primitives_result_InvalidTransaction. + + (* + Enum InvalidHeader + { + ty_params := []; + variants := + [ + { + name := "PrevrandaoNotSet"; + item := StructTuple []; + discriminant := None; + }; + { + name := "ExcessBlobGasNotSet"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidHeader::PrevrandaoNotSet" + |) in + M.alloc (| M.read (| Value.String "PrevrandaoNotSet" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidHeader::ExcessBlobGasNotSet" + |) in + M.alloc (| M.read (| Value.String "ExcessBlobGasNotSet" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_result_InvalidHeader. + + Module Impl_core_marker_Copy_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_result_InvalidHeader. + + Module Impl_core_clone_Clone_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_result_InvalidHeader. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_InvalidHeader. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::InvalidHeader" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::InvalidHeader" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_result_InvalidHeader. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_result_InvalidHeader. + + Module Impl_core_cmp_Eq_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_result_InvalidHeader. + + Module Impl_core_hash_Hash_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::InvalidHeader" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_result_InvalidHeader. + + Module Impl_core_error_Error_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + Axiom Implements : + M.IsTraitInstance + "core::error::Error" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_error_Error_for_revm_primitives_result_InvalidHeader. + + Module Impl_core_fmt_Display_for_revm_primitives_result_InvalidHeader. + Definition Self : Ty.t := Ty.path "revm_primitives::result::InvalidHeader". + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::PrevrandaoNotSet => write!(f, "`prevrandao` not set"), + Self::ExcessBlobGasNotSet => write!(f, "`excess_blob_gas` not set"), + } + } + *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidHeader::PrevrandaoNotSet" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array [ M.read (| Value.String "`prevrandao` not set" |) ] + |)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::InvalidHeader::ExcessBlobGasNotSet" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_fmt", + [] + |), + [ + M.read (| f |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ M.read (| Value.String "`excess_blob_gas` not set" |) ] + |)) + ] + |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Display" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Display_for_revm_primitives_result_InvalidHeader. + + (* + Enum SuccessReason + { + ty_params := []; + variants := + [ + { + name := "Stop"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Return"; + item := StructTuple []; + discriminant := None; + }; + { + name := "SelfDestruct"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_result_SuccessReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::SuccessReason". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::SuccessReason::Stop" + |) in + M.alloc (| M.read (| Value.String "Stop" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::SuccessReason::Return" + |) in + M.alloc (| M.read (| Value.String "Return" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::SuccessReason::SelfDestruct" + |) in + M.alloc (| M.read (| Value.String "SelfDestruct" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_result_SuccessReason. + + Module Impl_core_clone_Clone_for_revm_primitives_result_SuccessReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::SuccessReason". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_result_SuccessReason. + + Module Impl_core_marker_Copy_for_revm_primitives_result_SuccessReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::SuccessReason". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_result_SuccessReason. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_SuccessReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::SuccessReason". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_SuccessReason. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_result_SuccessReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::SuccessReason". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::SuccessReason" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::SuccessReason" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_result_SuccessReason. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_result_SuccessReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::SuccessReason". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_result_SuccessReason. + + Module Impl_core_cmp_Eq_for_revm_primitives_result_SuccessReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::SuccessReason". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_result_SuccessReason. + + Module Impl_core_hash_Hash_for_revm_primitives_result_SuccessReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::SuccessReason". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::SuccessReason" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_result_SuccessReason. + + (* + Enum HaltReason + { + ty_params := []; + variants := + [ + { + name := "OutOfGas"; + item := StructTuple [ Ty.path "revm_primitives::result::OutOfGasError" ]; + discriminant := None; + }; + { + name := "OpcodeNotFound"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidFEOpcode"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidJump"; + item := StructTuple []; + discriminant := None; + }; + { + name := "NotActivated"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StackUnderflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StackOverflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "OutOfOffset"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CreateCollision"; + item := StructTuple []; + discriminant := None; + }; + { + name := "PrecompileError"; + item := StructTuple []; + discriminant := None; + }; + { + name := "NonceOverflow"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CreateContractSizeLimit"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CreateContractStartingWithEF"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CreateInitCodeSizeLimit"; + item := StructTuple []; + discriminant := None; + }; + { + name := "OverflowPayment"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StateChangeDuringStaticCall"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CallNotAllowedInsideStatic"; + item := StructTuple []; + discriminant := None; + }; + { + name := "OutOfFunds"; + item := StructTuple []; + discriminant := None; + }; + { + name := "CallTooDeep"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_result_HaltReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::HaltReason". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::HaltReason::OutOfGas", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "OutOfGas" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::OpcodeNotFound" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "OpcodeNotFound" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::InvalidFEOpcode" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "InvalidFEOpcode" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::InvalidJump" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "InvalidJump" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::NotActivated" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "NotActivated" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::StackUnderflow" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "StackUnderflow" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::StackOverflow" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "StackOverflow" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::OutOfOffset" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "OutOfOffset" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CreateCollision" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "CreateCollision" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::PrecompileError" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "PrecompileError" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::NonceOverflow" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "NonceOverflow" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CreateContractSizeLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "CreateContractSizeLimit" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CreateContractStartingWithEF" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "CreateContractStartingWithEF" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CreateInitCodeSizeLimit" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "CreateInitCodeSizeLimit" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::OverflowPayment" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "OverflowPayment" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::StateChangeDuringStaticCall" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "StateChangeDuringStaticCall" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CallNotAllowedInsideStatic" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "CallNotAllowedInsideStatic" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::OutOfFunds" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "OutOfFunds" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::HaltReason::CallTooDeep" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "CallTooDeep" |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_result_HaltReason. + + Module Impl_core_clone_Clone_for_revm_primitives_result_HaltReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::HaltReason". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_result_HaltReason. + + Module Impl_core_marker_Copy_for_revm_primitives_result_HaltReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::HaltReason". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_result_HaltReason. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_HaltReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::HaltReason". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_HaltReason. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_result_HaltReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::HaltReason". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::HaltReason" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::HaltReason" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm_primitives::result::HaltReason::OutOfGas", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm_primitives::result::HaltReason::OutOfGas", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::result::OutOfGasError", + [ Ty.path "revm_primitives::result::OutOfGasError" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool true |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_result_HaltReason. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_result_HaltReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::HaltReason". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_result_HaltReason. + + Module Impl_core_cmp_Eq_for_revm_primitives_result_HaltReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::HaltReason". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_result_HaltReason. + + Module Impl_core_hash_Hash_for_revm_primitives_result_HaltReason. + Definition Self : Ty.t := Ty.path "revm_primitives::result::HaltReason". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::HaltReason" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::result::HaltReason::OutOfGas", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::result::OutOfGasError", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_result_HaltReason. + + (* + Enum OutOfGasError + { + ty_params := []; + variants := + [ + { + name := "Basic"; + item := StructTuple []; + discriminant := None; + }; + { + name := "MemoryLimit"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Memory"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Precompile"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InvalidOperand"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_primitives_result_OutOfGasError. + Definition Self : Ty.t := Ty.path "revm_primitives::result::OutOfGasError". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::Basic" + |) in + M.alloc (| M.read (| Value.String "Basic" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::MemoryLimit" + |) in + M.alloc (| M.read (| Value.String "MemoryLimit" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::Memory" + |) in + M.alloc (| M.read (| Value.String "Memory" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::Precompile" + |) in + M.alloc (| M.read (| Value.String "Precompile" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::result::OutOfGasError::InvalidOperand" + |) in + M.alloc (| M.read (| Value.String "InvalidOperand" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_result_OutOfGasError. + + Module Impl_core_marker_Copy_for_revm_primitives_result_OutOfGasError. + Definition Self : Ty.t := Ty.path "revm_primitives::result::OutOfGasError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_result_OutOfGasError. + + Module Impl_core_clone_Clone_for_revm_primitives_result_OutOfGasError. + Definition Self : Ty.t := Ty.path "revm_primitives::result::OutOfGasError". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_result_OutOfGasError. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_OutOfGasError. + Definition Self : Ty.t := Ty.path "revm_primitives::result::OutOfGasError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_result_OutOfGasError. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_result_OutOfGasError. + Definition Self : Ty.t := Ty.path "revm_primitives::result::OutOfGasError". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::OutOfGasError" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::OutOfGasError" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_result_OutOfGasError. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_result_OutOfGasError. + Definition Self : Ty.t := Ty.path "revm_primitives::result::OutOfGasError". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_result_OutOfGasError. + + Module Impl_core_cmp_Eq_for_revm_primitives_result_OutOfGasError. + Definition Self : Ty.t := Ty.path "revm_primitives::result::OutOfGasError". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_result_OutOfGasError. + + Module Impl_core_hash_Hash_for_revm_primitives_result_OutOfGasError. + Definition Self : Ty.t := Ty.path "revm_primitives::result::OutOfGasError". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::result::OutOfGasError" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_result_OutOfGasError. +End result. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/specification.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/specification.md new file mode 100644 index 00000000..a6d146a3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/specification.md @@ -0,0 +1,4587 @@ +# ๐Ÿ“ specification.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/specification.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module specification. + (* + Enum SpecId + { + ty_params := []; + variants := + [ + { + name := "FRONTIER"; + item := StructTuple []; + discriminant := Some 0; + }; + { + name := "FRONTIER_THAWING"; + item := StructTuple []; + discriminant := Some 1; + }; + { + name := "HOMESTEAD"; + item := StructTuple []; + discriminant := Some 2; + }; + { + name := "DAO_FORK"; + item := StructTuple []; + discriminant := Some 3; + }; + { + name := "TANGERINE"; + item := StructTuple []; + discriminant := Some 4; + }; + { + name := "SPURIOUS_DRAGON"; + item := StructTuple []; + discriminant := Some 5; + }; + { + name := "BYZANTIUM"; + item := StructTuple []; + discriminant := Some 6; + }; + { + name := "CONSTANTINOPLE"; + item := StructTuple []; + discriminant := Some 7; + }; + { + name := "PETERSBURG"; + item := StructTuple []; + discriminant := Some 8; + }; + { + name := "ISTANBUL"; + item := StructTuple []; + discriminant := Some 9; + }; + { + name := "MUIR_GLACIER"; + item := StructTuple []; + discriminant := Some 10; + }; + { + name := "BERLIN"; + item := StructTuple []; + discriminant := Some 11; + }; + { + name := "LONDON"; + item := StructTuple []; + discriminant := Some 12; + }; + { + name := "ARROW_GLACIER"; + item := StructTuple []; + discriminant := Some 13; + }; + { + name := "GRAY_GLACIER"; + item := StructTuple []; + discriminant := Some 14; + }; + { + name := "MERGE"; + item := StructTuple []; + discriminant := Some 15; + }; + { + name := "SHANGHAI"; + item := StructTuple []; + discriminant := Some 16; + }; + { + name := "CANCUN"; + item := StructTuple []; + discriminant := Some 17; + }; + { + name := "PRAGUE"; + item := StructTuple []; + discriminant := Some 18; + }; + { + name := "LATEST"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_SpecId. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_SpecId. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::FRONTIER" + |) in + M.alloc (| M.read (| Value.String "FRONTIER" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::FRONTIER_THAWING" + |) in + M.alloc (| M.read (| Value.String "FRONTIER_THAWING" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::HOMESTEAD" + |) in + M.alloc (| M.read (| Value.String "HOMESTEAD" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::DAO_FORK" + |) in + M.alloc (| M.read (| Value.String "DAO_FORK" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::TANGERINE" + |) in + M.alloc (| M.read (| Value.String "TANGERINE" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + |) in + M.alloc (| M.read (| Value.String "SPURIOUS_DRAGON" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::BYZANTIUM" + |) in + M.alloc (| M.read (| Value.String "BYZANTIUM" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::CONSTANTINOPLE" + |) in + M.alloc (| M.read (| Value.String "CONSTANTINOPLE" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::PETERSBURG" + |) in + M.alloc (| M.read (| Value.String "PETERSBURG" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::ISTANBUL" + |) in + M.alloc (| M.read (| Value.String "ISTANBUL" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::MUIR_GLACIER" + |) in + M.alloc (| M.read (| Value.String "MUIR_GLACIER" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::BERLIN" + |) in + M.alloc (| M.read (| Value.String "BERLIN" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::LONDON" + |) in + M.alloc (| M.read (| Value.String "LONDON" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::ARROW_GLACIER" + |) in + M.alloc (| M.read (| Value.String "ARROW_GLACIER" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::GRAY_GLACIER" + |) in + M.alloc (| M.read (| Value.String "GRAY_GLACIER" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::MERGE" + |) in + M.alloc (| M.read (| Value.String "MERGE" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::SHANGHAI" + |) in + M.alloc (| M.read (| Value.String "SHANGHAI" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::CANCUN" + |) in + M.alloc (| M.read (| Value.String "CANCUN" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::PRAGUE" + |) in + M.alloc (| M.read (| Value.String "PRAGUE" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::LATEST" + |) in + M.alloc (| M.read (| Value.String "LATEST" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_SpecId. + + Module Impl_core_default_Default_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::SpecId::LATEST" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_SpecId. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_SpecId. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::specification::SpecId" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::specification::SpecId" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_SpecId. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_SpecId. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_SpecId. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::specification::SpecId" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::specification::SpecId" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "u8", + [ Ty.path "u8" ], + "partial_cmp", + [] + |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_SpecId. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::specification::SpecId" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::specification::SpecId" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "u8", [], "cmp", [] |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_SpecId. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm_primitives::specification::SpecId" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u8", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_SpecId. + + Module Impl_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* enumn::N *) + Definition n (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ value ] => + ltac:(M.monadic + (let value := M.alloc (| value |) in + M.read (| + M.match_operator (| + value, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::FRONTIER" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 1 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm_primitives::specification::SpecId::FRONTIER_THAWING" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 2 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::HOMESTEAD" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 3 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::DAO_FORK" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 4 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::TANGERINE" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 5 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 6 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::BYZANTIUM" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 7 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CONSTANTINOPLE" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 8 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::PETERSBURG" [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 9 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::ISTANBUL" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 10 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm_primitives::specification::SpecId::MUIR_GLACIER" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 11 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::BERLIN" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 12 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::LONDON" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 13 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm_primitives::specification::SpecId::ARROW_GLACIER" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 14 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm_primitives::specification::SpecId::GRAY_GLACIER" + [] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 15 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::MERGE" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 16 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::SHANGHAI" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 17 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::CANCUN" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 18 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::PRAGUE" [] ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Integer 255 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "revm_primitives::specification::SpecId::LATEST" [] ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_n : M.IsAssociatedFunction Self "n" n. + (* + pub fn try_from_u8(spec_id: u8) -> Option { + Self::n(spec_id) + } + *) + Definition try_from_u8 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "n", + [] + |), + [ M.read (| spec_id |) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_try_from_u8 : M.IsAssociatedFunction Self "try_from_u8" try_from_u8. + + (* + pub const fn is_enabled_in(self, other: Self) -> bool { + Self::enabled(self, other) + } + *) + Definition is_enabled_in (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "enabled", + [] + |), + [ M.read (| self |); M.read (| other |) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_enabled_in : + M.IsAssociatedFunction Self "is_enabled_in" is_enabled_in. + + (* + pub const fn enabled(our: SpecId, other: SpecId) -> bool { + our as u8 >= other as u8 + } + *) + Definition enabled (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ our; other ] => + ltac:(M.monadic + (let our := M.alloc (| our |) in + let other := M.alloc (| other |) in + BinOp.Pure.ge (M.rust_cast (M.read (| our |))) (M.rust_cast (M.read (| other |))))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_enabled : M.IsAssociatedFunction Self "enabled" enabled. + End Impl_revm_primitives_specification_SpecId. + + + Module Impl_core_convert_From_ref__str_for_revm_primitives_specification_SpecId. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpecId". + + (* + fn from(name: &str) -> Self { + match name { + "Frontier" => Self::FRONTIER, + "Homestead" => Self::HOMESTEAD, + "Tangerine" => Self::TANGERINE, + "Spurious" => Self::SPURIOUS_DRAGON, + "Byzantium" => Self::BYZANTIUM, + "Constantinople" => Self::CONSTANTINOPLE, + "Petersburg" => Self::PETERSBURG, + "Istanbul" => Self::ISTANBUL, + "MuirGlacier" => Self::MUIR_GLACIER, + "Berlin" => Self::BERLIN, + "London" => Self::LONDON, + "Merge" => Self::MERGE, + "Shanghai" => Self::SHANGHAI, + "Cancun" => Self::CANCUN, + "Prague" => Self::PRAGUE, + #[cfg(feature = "optimism")] + "Bedrock" => SpecId::BEDROCK, + #[cfg(feature = "optimism")] + "Regolith" => SpecId::REGOLITH, + #[cfg(feature = "optimism")] + "Canyon" => SpecId::CANYON, + #[cfg(feature = "optimism")] + "Ecotone" => SpecId::ECOTONE, + _ => Self::LATEST, + } + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ name ] => + ltac:(M.monadic + (let name := M.alloc (| name |) in + M.read (| + M.match_operator (| + name, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Frontier" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::FRONTIER" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Homestead" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::HOMESTEAD" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Tangerine" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::TANGERINE" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Spurious" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Byzantium" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::BYZANTIUM" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.String "Constantinople" + |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::CONSTANTINOPLE" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.String "Petersburg" + |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::PETERSBURG" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Istanbul" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::ISTANBUL" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.String "MuirGlacier" + |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::MUIR_GLACIER" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Berlin" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::BERLIN" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "London" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::LONDON" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Merge" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::MERGE" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Shanghai" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::SHANGHAI" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Cancun" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::CANCUN" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.String "Prague" |) in + M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::PRAGUE" [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::LATEST" [] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) [ (* T *) Ty.apply (Ty.path "&") [ Ty.path "str" ] ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_ref__str_for_revm_primitives_specification_SpecId. + + Module Impl_core_convert_From_revm_primitives_specification_SpecId_for_ref__str. + Definition Self : Ty.t := Ty.apply (Ty.path "&") [ Ty.path "str" ]. + + (* + fn from(spec_id: SpecId) -> Self { + match spec_id { + SpecId::FRONTIER => "Frontier", + SpecId::FRONTIER_THAWING => "Frontier Thawing", + SpecId::HOMESTEAD => "Homestead", + SpecId::DAO_FORK => "DAO Fork", + SpecId::TANGERINE => "Tangerine", + SpecId::SPURIOUS_DRAGON => "Spurious", + SpecId::BYZANTIUM => "Byzantium", + SpecId::CONSTANTINOPLE => "Constantinople", + SpecId::PETERSBURG => "Petersburg", + SpecId::ISTANBUL => "Istanbul", + SpecId::MUIR_GLACIER => "MuirGlacier", + SpecId::BERLIN => "Berlin", + SpecId::LONDON => "London", + SpecId::ARROW_GLACIER => "Arrow Glacier", + SpecId::GRAY_GLACIER => "Gray Glacier", + SpecId::MERGE => "Merge", + SpecId::SHANGHAI => "Shanghai", + SpecId::CANCUN => "Cancun", + SpecId::PRAGUE => "Prague", + #[cfg(feature = "optimism")] + SpecId::BEDROCK => "Bedrock", + #[cfg(feature = "optimism")] + SpecId::REGOLITH => "Regolith", + #[cfg(feature = "optimism")] + SpecId::CANYON => "Canyon", + #[cfg(feature = "optimism")] + SpecId::ECOTONE => "Ecotone", + SpecId::LATEST => "Latest", + } + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + M.read (| + M.match_operator (| + spec_id, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::FRONTIER" + |) in + Value.String "Frontier")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::FRONTIER_THAWING" + |) in + Value.String "Frontier Thawing")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::HOMESTEAD" + |) in + Value.String "Homestead")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::DAO_FORK" + |) in + Value.String "DAO Fork")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::TANGERINE" + |) in + Value.String "Tangerine")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + |) in + Value.String "Spurious")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::BYZANTIUM" + |) in + Value.String "Byzantium")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::CONSTANTINOPLE" + |) in + Value.String "Constantinople")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::PETERSBURG" + |) in + Value.String "Petersburg")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::ISTANBUL" + |) in + Value.String "Istanbul")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::MUIR_GLACIER" + |) in + Value.String "MuirGlacier")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::BERLIN" |) in + Value.String "Berlin")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::LONDON" |) in + Value.String "London")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::ARROW_GLACIER" + |) in + Value.String "Arrow Glacier")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::GRAY_GLACIER" + |) in + Value.String "Gray Glacier")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::MERGE" |) in + Value.String "Merge")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::SHANGHAI" + |) in + Value.String "Shanghai")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::CANCUN" |) in + Value.String "Cancun")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::PRAGUE" |) in + Value.String "Prague")); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::LATEST" |) in + Value.String "Latest")) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) [ (* T *) Ty.path "revm_primitives::specification::SpecId" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_primitives_specification_SpecId_for_ref__str. + + (* Trait *) + Module Spec. + Definition enabled (Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec_id ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "enabled", + [] + |), + [ + M.read (| M.get_constant (| "revm_primitives::specification::Spec::SPEC_ID" |) |); + M.read (| spec_id |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_enabled : + M.IsProvidedMethod "revm_primitives::specification::Spec" "enabled" enabled. + End Spec. + + (* StructTuple + { + name := "FrontierSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "FrontierSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::FrontierSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_FrontierSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_FrontierSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_FrontierSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::FrontierSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::FRONTIER" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_FrontierSpec. + + (* StructTuple + { + name := "HomesteadSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "HomesteadSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::HomesteadSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_HomesteadSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_HomesteadSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::HomesteadSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::HOMESTEAD" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_HomesteadSpec. + + (* StructTuple + { + name := "TangerineSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "TangerineSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::TangerineSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_TangerineSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_TangerineSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_TangerineSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::TangerineSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::TANGERINE" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_TangerineSpec. + + (* StructTuple + { + name := "SpuriousDragonSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "SpuriousDragonSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::SpuriousDragonSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_SpuriousDragonSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_SpuriousDragonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::SpuriousDragonSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" [] + |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_SpuriousDragonSpec. + + (* StructTuple + { + name := "ByzantiumSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "ByzantiumSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::ByzantiumSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_ByzantiumSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_ByzantiumSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ByzantiumSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::BYZANTIUM" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_ByzantiumSpec. + + (* StructTuple + { + name := "PetersburgSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "PetersburgSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::PetersburgSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_PetersburgSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_PetersburgSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PetersburgSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "revm_primitives::specification::SpecId::PETERSBURG" [] + |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_PetersburgSpec. + + (* StructTuple + { + name := "IstanbulSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "IstanbulSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::IstanbulSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_IstanbulSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_IstanbulSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::IstanbulSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::ISTANBUL" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_IstanbulSpec. + + (* StructTuple + { + name := "BerlinSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "BerlinSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::BerlinSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_BerlinSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_BerlinSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_BerlinSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::BerlinSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::BERLIN" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_BerlinSpec. + + (* StructTuple + { + name := "LondonSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "LondonSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::LondonSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_LondonSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_LondonSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_LondonSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LondonSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::LONDON" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_LondonSpec. + + (* StructTuple + { + name := "MergeSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "MergeSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::MergeSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_MergeSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_MergeSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_MergeSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::MergeSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::MERGE" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_MergeSpec. + + (* StructTuple + { + name := "ShanghaiSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "ShanghaiSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::ShanghaiSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_ShanghaiSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_ShanghaiSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::ShanghaiSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::SHANGHAI" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_ShanghaiSpec. + + (* StructTuple + { + name := "CancunSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "CancunSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::CancunSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_CancunSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_CancunSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_CancunSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::CancunSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::CANCUN" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_CancunSpec. + + (* StructTuple + { + name := "PragueSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "PragueSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::PragueSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_PragueSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_PragueSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_PragueSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::PragueSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::PRAGUE" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_PragueSpec. + + (* StructTuple + { + name := "LatestSpec"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_marker_Copy_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_fmt_Debug_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "LatestSpec" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_default_Default_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm_primitives::specification::LatestSpec" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_cmp_Eq_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_cmp_Ord_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_specification_LatestSpec. + + Module Impl_core_hash_Hash_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_specification_LatestSpec. + + Module Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_LatestSpec. + Definition Self : Ty.t := Ty.path "revm_primitives::specification::LatestSpec". + + (* const SPEC_ID: SpecId = $spec_id; *) + (* Ty.path "revm_primitives::specification::SpecId" *) + Definition value_SPEC_ID : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| Value.StructTuple "revm_primitives::specification::SpecId::LATEST" [] |))). + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::specification::Spec" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("value_SPEC_ID", InstanceField.Constant value_SPEC_ID) ]. + End Impl_revm_primitives_specification_Spec_for_revm_primitives_specification_LatestSpec. +End specification. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/state.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/state.md new file mode 100644 index 00000000..4b141228 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/state.md @@ -0,0 +1,2577 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/state.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module state. + Axiom State : + (Ty.path "revm_primitives::state::State") = + (Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ]). + + Axiom TransientStorage : + (Ty.path "revm_primitives::state::TransientStorage") = + (Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple [ Ty.path "alloy_primitives::bits::address::Address"; Ty.path "ruint::Uint" ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ]). + + Axiom Storage : + (Ty.path "revm_primitives::state::Storage") = + (Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ]). + + (* StructRecord + { + name := "Account"; + ty_params := []; + fields := + [ + ("info", Ty.path "revm_primitives::state::AccountInfo"); + ("storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ]); + ("status", Ty.path "revm_primitives::state::AccountStatus") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_primitives_state_Account. + Definition Self : Ty.t := Ty.path "revm_primitives::state::Account". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Account" |); + M.read (| Value.String "info" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "info" + |)); + M.read (| Value.String "storage" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "storage" + |)); + M.read (| Value.String "status" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_state_Account. + + Module Impl_core_clone_Clone_for_revm_primitives_state_Account. + Definition Self : Ty.t := Ty.path "revm_primitives::state::Account". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::state::Account" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountInfo", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "info" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "storage" + |) + ] + |)); + ("status", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountStatus", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_state_Account. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_state_Account. + Definition Self : Ty.t := Ty.path "revm_primitives::state::Account". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_state_Account. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_state_Account. + Definition Self : Ty.t := Ty.path "revm_primitives::state::Account". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::state::AccountInfo", + [ Ty.path "revm_primitives::state::AccountInfo" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "info" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::state::Account", + "info" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "storage" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::state::Account", + "storage" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::state::AccountStatus", + [ Ty.path "revm_primitives::state::AccountStatus" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::state::Account", + "status" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_state_Account. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_state_Account. + Definition Self : Ty.t := Ty.path "revm_primitives::state::Account". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_state_Account. + + Module Impl_core_cmp_Eq_for_revm_primitives_state_Account. + Definition Self : Ty.t := Ty.path "revm_primitives::state::Account". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_state_Account. + + Module Impl_core_default_Default_for_revm_primitives_state_Account. + Definition Self : Ty.t := Ty.path "revm_primitives::state::Account". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::state::Account" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::AccountInfo", + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("status", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::AccountStatus", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_state_Account. + + Module Impl_core_fmt_Debug_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "AccountStatus" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::state::AccountStatus", + 0 + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_state_AccountStatus. + + Module Impl_core_clone_Clone_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_state_AccountStatus. + + Module Impl_core_marker_Copy_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_primitives_state_AccountStatus. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_state_AccountStatus. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::state::_::InternalBitFlags", + [ Ty.path "revm_primitives::state::_::InternalBitFlags" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::state::AccountStatus", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_primitives::state::AccountStatus", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_state_AccountStatus. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_state_AccountStatus. + + Module Impl_core_cmp_Eq_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_state_AccountStatus. + + Module Impl_core_cmp_PartialOrd_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "revm_primitives::state::_::InternalBitFlags", + [ Ty.path "revm_primitives::state::_::InternalBitFlags" ], + "partial_cmp", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::state::AccountStatus", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_primitives::state::AccountStatus", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_primitives_state_AccountStatus. + + Module Impl_core_cmp_Ord_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::Ord", + Ty.path "revm_primitives::state::_::InternalBitFlags", + [], + "cmp", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::state::AccountStatus", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm_primitives::state::AccountStatus", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_primitives_state_AccountStatus. + + Module Impl_core_hash_Hash_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::state::_::InternalBitFlags", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm_primitives::state::AccountStatus", + 0 + |); + M.read (| state |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_state_AccountStatus. + + Module Impl_core_default_Default_for_revm_primitives_state_AccountStatus. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountStatus". + + (* + fn default() -> Self { + Self::Loaded + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (M.read (| M.get_constant (| "revm_primitives::state::Loaded" |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_state_AccountStatus. + + Module Impl_revm_primitives_state_Account. + Definition Self : Ty.t := Ty.path "revm_primitives::state::Account". + + (* + pub fn new_not_existing() -> Self { + Self { + info: AccountInfo::default(), + storage: HashMap::new(), + status: AccountStatus::LoadedAsNotExisting, + } + } + *) + Definition new_not_existing (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::state::Account" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::AccountInfo", + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("status", + M.read (| M.get_constant (| "revm_primitives::state::LoadedAsNotExisting" |) |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_not_existing : + M.IsAssociatedFunction Self "new_not_existing" new_not_existing. + + (* + pub fn mark_selfdestruct(&mut self) { + self.status |= AccountStatus::SelfDestructed; + } + *) + Definition mark_selfdestruct (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::BitOrAssign", + Ty.path "revm_primitives::state::AccountStatus", + [ Ty.path "revm_primitives::state::AccountStatus" ], + "bitor_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::SelfDestructed" |) |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_mark_selfdestruct : + M.IsAssociatedFunction Self "mark_selfdestruct" mark_selfdestruct. + + (* + pub fn unmark_selfdestruct(&mut self) { + self.status -= AccountStatus::SelfDestructed; + } + *) + Definition unmark_selfdestruct (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::SubAssign", + Ty.path "revm_primitives::state::AccountStatus", + [ Ty.path "revm_primitives::state::AccountStatus" ], + "sub_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::SelfDestructed" |) |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_unmark_selfdestruct : + M.IsAssociatedFunction Self "unmark_selfdestruct" unmark_selfdestruct. + + (* + pub fn is_selfdestructed(&self) -> bool { + self.status.contains(AccountStatus::SelfDestructed) + } + *) + Definition is_selfdestructed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountStatus", + "contains", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::SelfDestructed" |) |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_selfdestructed : + M.IsAssociatedFunction Self "is_selfdestructed" is_selfdestructed. + + (* + pub fn mark_touch(&mut self) { + self.status |= AccountStatus::Touched; + } + *) + Definition mark_touch (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::BitOrAssign", + Ty.path "revm_primitives::state::AccountStatus", + [ Ty.path "revm_primitives::state::AccountStatus" ], + "bitor_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::Touched" |) |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_mark_touch : M.IsAssociatedFunction Self "mark_touch" mark_touch. + + (* + pub fn unmark_touch(&mut self) { + self.status -= AccountStatus::Touched; + } + *) + Definition unmark_touch (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::SubAssign", + Ty.path "revm_primitives::state::AccountStatus", + [ Ty.path "revm_primitives::state::AccountStatus" ], + "sub_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::Touched" |) |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_unmark_touch : M.IsAssociatedFunction Self "unmark_touch" unmark_touch. + + (* + pub fn is_touched(&self) -> bool { + self.status.contains(AccountStatus::Touched) + } + *) + Definition is_touched (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountStatus", + "contains", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::Touched" |) |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_touched : M.IsAssociatedFunction Self "is_touched" is_touched. + + (* + pub fn mark_created(&mut self) { + self.status |= AccountStatus::Created; + } + *) + Definition mark_created (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::bit::BitOrAssign", + Ty.path "revm_primitives::state::AccountStatus", + [ Ty.path "revm_primitives::state::AccountStatus" ], + "bitor_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::Created" |) |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_mark_created : M.IsAssociatedFunction Self "mark_created" mark_created. + + (* + pub fn unmark_created(&mut self) { + self.status -= AccountStatus::Created; + } + *) + Definition unmark_created (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::SubAssign", + Ty.path "revm_primitives::state::AccountStatus", + [ Ty.path "revm_primitives::state::AccountStatus" ], + "sub_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::Created" |) |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_unmark_created : + M.IsAssociatedFunction Self "unmark_created" unmark_created. + + (* + pub fn is_loaded_as_not_existing(&self) -> bool { + self.status.contains(AccountStatus::LoadedAsNotExisting) + } + *) + Definition is_loaded_as_not_existing (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountStatus", + "contains", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::LoadedAsNotExisting" |) |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_loaded_as_not_existing : + M.IsAssociatedFunction Self "is_loaded_as_not_existing" is_loaded_as_not_existing. + + (* + pub fn is_created(&self) -> bool { + self.status.contains(AccountStatus::Created) + } + *) + Definition is_created (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountStatus", + "contains", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "status" + |); + M.read (| M.get_constant (| "revm_primitives::state::Created" |) |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_created : M.IsAssociatedFunction Self "is_created" is_created. + + (* + pub fn is_empty(&self) -> bool { + self.info.is_empty() + } + *) + Definition is_empty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "info" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_empty : M.IsAssociatedFunction Self "is_empty" is_empty. + + (* + pub fn changed_storage_slots(&self) -> impl Iterator { + self.storage.iter().filter(|(_, slot)| slot.is_changed()) + } + *) + Definition changed_storage_slots (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" ], + [], + "filter", + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + ] + (Ty.path "bool") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::Account", + "storage" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let slot := M.alloc (| ฮณ1_1 |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::StorageSlot", + "is_changed", + [] + |), + [ M.read (| M.read (| slot |) |) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_changed_storage_slots : + M.IsAssociatedFunction Self "changed_storage_slots" changed_storage_slots. + End Impl_revm_primitives_state_Account. + + Module Impl_core_convert_From_revm_primitives_state_AccountInfo_for_revm_primitives_state_Account. + Definition Self : Ty.t := Ty.path "revm_primitives::state::Account". + + (* + fn from(info: AccountInfo) -> Self { + Self { + info, + storage: HashMap::new(), + status: AccountStatus::Loaded, + } + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ info ] => + ltac:(M.monadic + (let info := M.alloc (| info |) in + Value.StructRecord + "revm_primitives::state::Account" + [ + ("info", M.read (| info |)); + ("storage", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("status", M.read (| M.get_constant (| "revm_primitives::state::Loaded" |) |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) [ (* T *) Ty.path "revm_primitives::state::AccountInfo" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_primitives_state_AccountInfo_for_revm_primitives_state_Account. + + (* StructRecord + { + name := "StorageSlot"; + ty_params := []; + fields := + [ + ("previous_or_original_value", Ty.path "ruint::Uint"); + ("present_value", Ty.path "ruint::Uint") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_primitives_state_StorageSlot. + Definition Self : Ty.t := Ty.path "revm_primitives::state::StorageSlot". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "StorageSlot" |); + M.read (| Value.String "previous_or_original_value" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |)); + M.read (| Value.String "present_value" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_state_StorageSlot. + + Module Impl_core_clone_Clone_for_revm_primitives_state_StorageSlot. + Definition Self : Ty.t := Ty.path "revm_primitives::state::StorageSlot". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::state::StorageSlot" + [ + ("previous_or_original_value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |) + ] + |)); + ("present_value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_state_StorageSlot. + + Module Impl_core_default_Default_for_revm_primitives_state_StorageSlot. + Definition Self : Ty.t := Ty.path "revm_primitives::state::StorageSlot". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::state::StorageSlot" + [ + ("previous_or_original_value", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "ruint::Uint", + [], + "default", + [] + |), + [] + |)); + ("present_value", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "ruint::Uint", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_state_StorageSlot. + + Module Impl_core_marker_StructuralPartialEq_for_revm_primitives_state_StorageSlot. + Definition Self : Ty.t := Ty.path "revm_primitives::state::StorageSlot". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_primitives_state_StorageSlot. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_state_StorageSlot. + Definition Self : Ty.t := Ty.path "revm_primitives::state::StorageSlot". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "present_value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_state_StorageSlot. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_state_StorageSlot. + Definition Self : Ty.t := Ty.path "revm_primitives::state::StorageSlot". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_state_StorageSlot. + + Module Impl_core_cmp_Eq_for_revm_primitives_state_StorageSlot. + Definition Self : Ty.t := Ty.path "revm_primitives::state::StorageSlot". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_state_StorageSlot. + + Module Impl_core_hash_Hash_for_revm_primitives_state_StorageSlot. + Definition Self : Ty.t := Ty.path "revm_primitives::state::StorageSlot". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "present_value" + |); + M.read (| state |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_state_StorageSlot. + + Module Impl_revm_primitives_state_StorageSlot. + Definition Self : Ty.t := Ty.path "revm_primitives::state::StorageSlot". + + (* + pub fn new(original: U256) -> Self { + Self { + previous_or_original_value: original, + present_value: original, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ original ] => + ltac:(M.monadic + (let original := M.alloc (| original |) in + Value.StructRecord + "revm_primitives::state::StorageSlot" + [ + ("previous_or_original_value", M.read (| original |)); + ("present_value", M.read (| original |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn new_changed(previous_or_original_value: U256, present_value: U256) -> Self { + Self { + previous_or_original_value, + present_value, + } + } + *) + Definition new_changed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ previous_or_original_value; present_value ] => + ltac:(M.monadic + (let previous_or_original_value := M.alloc (| previous_or_original_value |) in + let present_value := M.alloc (| present_value |) in + Value.StructRecord + "revm_primitives::state::StorageSlot" + [ + ("previous_or_original_value", M.read (| previous_or_original_value |)); + ("present_value", M.read (| present_value |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_changed : M.IsAssociatedFunction Self "new_changed" new_changed. + + (* + pub fn is_changed(&self) -> bool { + self.previous_or_original_value != self.present_value + } + *) + Definition is_changed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_changed : M.IsAssociatedFunction Self "is_changed" is_changed. + + (* + pub fn original_value(&self) -> U256 { + self.previous_or_original_value + } + *) + Definition original_value (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_original_value : + M.IsAssociatedFunction Self "original_value" original_value. + + (* + pub fn present_value(&self) -> U256 { + self.present_value + } + *) + Definition present_value (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_present_value : + M.IsAssociatedFunction Self "present_value" present_value. + End Impl_revm_primitives_state_StorageSlot. + + (* StructRecord + { + name := "AccountInfo"; + ty_params := []; + fields := + [ + ("balance", Ty.path "ruint::Uint"); + ("nonce", Ty.path "u64"); + ("code_hash", Ty.path "alloy_primitives::bits::fixed::FixedBytes"); + ("code", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::bytecode::Bytecode" ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_primitives_state_AccountInfo. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountInfo". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm_primitives::state::AccountInfo" + [ + ("balance", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "balance" + |) + ] + |)); + ("nonce", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "u64", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + ] + |)); + ("code_hash", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code_hash" + |) + ] + |)); + ("code", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::bytecode::Bytecode" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_primitives_state_AccountInfo. + + Module Impl_core_fmt_Debug_for_revm_primitives_state_AccountInfo. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountInfo". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "AccountInfo" |); + M.read (| Value.String "balance" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "balance" + |)); + M.read (| Value.String "nonce" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "nonce" + |)); + M.read (| Value.String "code_hash" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code_hash" + |)); + M.read (| Value.String "code" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_primitives_state_AccountInfo. + + Module Impl_core_marker_StructuralEq_for_revm_primitives_state_AccountInfo. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountInfo". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_primitives_state_AccountInfo. + + Module Impl_core_cmp_Eq_for_revm_primitives_state_AccountInfo. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountInfo". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_primitives_state_AccountInfo. + + Module Impl_core_default_Default_for_revm_primitives_state_AccountInfo. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountInfo". + + (* + fn default() -> Self { + Self { + balance: U256::ZERO, + code_hash: KECCAK_EMPTY, + code: Some(Bytecode::default()), + nonce: 0, + } + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm_primitives::state::AccountInfo" + [ + ("balance", M.read (| M.get_constant (| "ruint::ZERO" |) |)); + ("code_hash", + M.read (| M.get_constant (| "revm_primitives::utilities::KECCAK_EMPTY" |) |)); + ("code", + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "default", + [] + |), + [] + |) + ]); + ("nonce", Value.Integer 0) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_primitives_state_AccountInfo. + + Module Impl_core_cmp_PartialEq_for_revm_primitives_state_AccountInfo. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountInfo". + + (* + fn eq(&self, other: &Self) -> bool { + self.balance == other.balance + && self.nonce == other.nonce + && self.code_hash == other.code_hash + } + *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "balance" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::state::AccountInfo", + "balance" + |) + ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code_hash" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm_primitives::state::AccountInfo", + "code_hash" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_primitives_state_AccountInfo. + + Module Impl_core_hash_Hash_for_revm_primitives_state_AccountInfo. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountInfo". + + (* + fn hash(&self, state: &mut H) { + self.balance.hash(state); + self.nonce.hash(state); + self.code_hash.hash(state); + } + *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "balance" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "u64", [], "hash", [ H ] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "nonce" + |); + M.read (| state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [], + "hash", + [ H ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code_hash" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_primitives_state_AccountInfo. + + Module Impl_revm_primitives_state_AccountInfo. + Definition Self : Ty.t := Ty.path "revm_primitives::state::AccountInfo". + + (* + pub fn new(balance: U256, nonce: u64, code_hash: B256, code: Bytecode) -> Self { + Self { + balance, + nonce, + code: Some(code), + code_hash, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ balance; nonce; code_hash; code ] => + ltac:(M.monadic + (let balance := M.alloc (| balance |) in + let nonce := M.alloc (| nonce |) in + let code_hash := M.alloc (| code_hash |) in + let code := M.alloc (| code |) in + Value.StructRecord + "revm_primitives::state::AccountInfo" + [ + ("balance", M.read (| balance |)); + ("nonce", M.read (| nonce |)); + ("code", Value.StructTuple "core::option::Option::Some" [ M.read (| code |) ]); + ("code_hash", M.read (| code_hash |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn without_code(mut self) -> Self { + self.take_bytecode(); + self + } + *) + Definition without_code (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "take_bytecode", + [] + |), + [ self ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_without_code : M.IsAssociatedFunction Self "without_code" without_code. + + (* + pub fn is_empty(&self) -> bool { + let code_empty = self.is_empty_code_hash() || self.code_hash == B256::ZERO; + code_empty && self.balance == U256::ZERO && self.nonce == 0 + } + *) + Definition is_empty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ code_empty := + M.alloc (| + LogicalOp.or (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "is_empty_code_hash", + [] + |), + [ M.read (| self |) ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code_hash" + |); + M.get_constant (| "alloy_primitives::bits::fixed::ZERO" |) + ] + |))) + |) + |) in + M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + M.read (| code_empty |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "balance" + |); + M.get_constant (| "ruint::ZERO" |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + |)) + (Value.Integer 0))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_empty : M.IsAssociatedFunction Self "is_empty" is_empty. + + (* + pub fn exists(&self) -> bool { + !self.is_empty() + } + *) + Definition exists_ (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "is_empty", + [] + |), + [ M.read (| self |) ] + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_exists_ : M.IsAssociatedFunction Self "exists_" exists_. + + (* + pub fn has_no_code_and_nonce(&self) -> bool { + self.is_empty_code_hash() && self.nonce == 0 + } + *) + Definition has_no_code_and_nonce (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + LogicalOp.and (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "is_empty_code_hash", + [] + |), + [ M.read (| self |) ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + |)) + (Value.Integer 0))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_has_no_code_and_nonce : + M.IsAssociatedFunction Self "has_no_code_and_nonce" has_no_code_and_nonce. + + (* + pub fn code_hash(&self) -> B256 { + self.code_hash + } + *) + Definition code_hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code_hash" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_code_hash : M.IsAssociatedFunction Self "code_hash" code_hash. + + (* + pub fn is_empty_code_hash(&self) -> bool { + self.code_hash == KECCAK_EMPTY + } + *) + Definition is_empty_code_hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code_hash" + |); + M.get_constant (| "revm_primitives::utilities::KECCAK_EMPTY" |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_empty_code_hash : + M.IsAssociatedFunction Self "is_empty_code_hash" is_empty_code_hash. + + (* + pub fn take_bytecode(&mut self) -> Option { + self.code.take() + } + *) + Definition take_bytecode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::bytecode::Bytecode" ], + "take", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm_primitives::state::AccountInfo", + "code" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_take_bytecode : + M.IsAssociatedFunction Self "take_bytecode" take_bytecode. + + (* + pub fn from_balance(balance: U256) -> Self { + AccountInfo { + balance, + ..Default::default() + } + } + *) + Definition from_balance (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ balance ] => + ltac:(M.monadic + (let balance := M.alloc (| balance |) in + M.struct_record_update + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::AccountInfo", + [], + "default", + [] + |), + [] + |)) + [ ("balance", M.read (| balance |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_from_balance : M.IsAssociatedFunction Self "from_balance" from_balance. + End Impl_revm_primitives_state_AccountInfo. +End state. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/utilities.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/utilities.md new file mode 100644 index 00000000..f791f7f8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/primitives/utilities.md @@ -0,0 +1,262 @@ +# ๐Ÿ“ utilities.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/primitives/utilities.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module utilities. + Definition value_KECCAK_EMPTY : Value.t := + M.run + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + "new", + [] + |), + [ M.read (| M.get_constant (| "revm_primitives::utilities::KECCAK_EMPTY::RES" |) |) ] + |) + |))). + + (* + pub fn calc_excess_blob_gas(parent_excess_blob_gas: u64, parent_blob_gas_used: u64) -> u64 { + (parent_excess_blob_gas + parent_blob_gas_used).saturating_sub(TARGET_BLOB_GAS_PER_BLOCK) + } + *) + Definition calc_excess_blob_gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ parent_excess_blob_gas; parent_blob_gas_used ] => + ltac:(M.monadic + (let parent_excess_blob_gas := M.alloc (| parent_excess_blob_gas |) in + let parent_blob_gas_used := M.alloc (| parent_blob_gas_used |) in + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "saturating_sub", [] |), + [ + BinOp.Wrap.add + Integer.U64 + (M.read (| parent_excess_blob_gas |)) + (M.read (| parent_blob_gas_used |)); + M.read (| + M.get_constant (| "revm_primitives::constants::TARGET_BLOB_GAS_PER_BLOCK" |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_calc_excess_blob_gas : + M.IsFunction "revm_primitives::utilities::calc_excess_blob_gas" calc_excess_blob_gas. + + (* + pub fn calc_blob_gasprice(excess_blob_gas: u64) -> u128 { + fake_exponential( + MIN_BLOB_GASPRICE, + excess_blob_gas, + BLOB_GASPRICE_UPDATE_FRACTION, + ) + } + *) + Definition calc_blob_gasprice (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ excess_blob_gas ] => + ltac:(M.monadic + (let excess_blob_gas := M.alloc (| excess_blob_gas |) in + M.call_closure (| + M.get_function (| "revm_primitives::utilities::fake_exponential", [] |), + [ + M.read (| M.get_constant (| "revm_primitives::constants::MIN_BLOB_GASPRICE" |) |); + M.read (| excess_blob_gas |); + M.read (| + M.get_constant (| "revm_primitives::constants::BLOB_GASPRICE_UPDATE_FRACTION" |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_calc_blob_gasprice : + M.IsFunction "revm_primitives::utilities::calc_blob_gasprice" calc_blob_gasprice. + + (* + pub fn fake_exponential(factor: u64, numerator: u64, denominator: u64) -> u128 { + assert_ne!(denominator, 0, "attempt to divide by zero"); + let factor = factor as u128; + let numerator = numerator as u128; + let denominator = denominator as u128; + + let mut i = 1; + let mut output = 0; + let mut numerator_accum = factor * denominator; + while numerator_accum > 0 { + output += numerator_accum; + + // Denominator is asserted as not zero at the start of the function. + numerator_accum = (numerator_accum * numerator) / (denominator * i); + i += 1; + } + output / denominator + } + *) + Definition fake_exponential (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ factor; numerator; denominator ] => + ltac:(M.monadic + (let factor := M.alloc (| factor |) in + let numerator := M.alloc (| numerator |) in + let denominator := M.alloc (| denominator |) in + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [ denominator; M.alloc (| Value.Integer 0 |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let left_val := M.copy (| ฮณ0_0 |) in + let right_val := M.copy (| ฮณ0_1 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| M.read (| left_val |) |)) + (M.read (| M.read (| right_val |) |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ kind := + M.alloc (| + Value.StructTuple "core::panicking::AssertKind::Ne" [] + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "core::panicking::assert_failed", + [ Ty.path "u64"; Ty.path "u64" ] + |), + [ + M.read (| kind |); + M.read (| left_val |); + M.read (| right_val |); + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String "attempt to divide by zero" + |) + ] + |)) + ] + |) + ] + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + let~ factor := M.alloc (| M.rust_cast (M.read (| factor |)) |) in + let~ numerator := M.alloc (| M.rust_cast (M.read (| numerator |)) |) in + let~ denominator := M.alloc (| M.rust_cast (M.read (| denominator |)) |) in + let~ i := M.alloc (| Value.Integer 1 |) in + let~ output := M.alloc (| Value.Integer 0 |) in + let~ numerator_accum := + M.alloc (| + BinOp.Wrap.mul Integer.U128 (M.read (| factor |)) (M.read (| denominator |)) + |) in + let~ _ := + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt (M.read (| numerator_accum |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + let ฮฒ := output in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.U128 + (M.read (| ฮฒ |)) + (M.read (| numerator_accum |)) + |) in + let~ _ := + M.write (| + numerator_accum, + BinOp.Wrap.div + Integer.U128 + (BinOp.Wrap.mul + Integer.U128 + (M.read (| numerator_accum |)) + (M.read (| numerator |))) + (BinOp.Wrap.mul + Integer.U128 + (M.read (| denominator |)) + (M.read (| i |))) + |) in + let~ _ := + let ฮฒ := i in + M.write (| + ฮฒ, + BinOp.Wrap.add Integer.U128 (M.read (| ฮฒ |)) (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| M.never_to_any (| M.read (| M.break (||) |) |) |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) in + M.alloc (| BinOp.Wrap.div Integer.U128 (M.read (| output |)) (M.read (| denominator |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_fake_exponential : + M.IsFunction "revm_primitives::utilities::fake_exponential" fake_exponential. +End utilities. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/builder.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/builder.md new file mode 100644 index 00000000..7b41da79 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/builder.md @@ -0,0 +1,2614 @@ +# ๐Ÿ“ builder.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/builder.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module builder. + (* StructRecord + { + name := "EvmBuilder"; + ty_params := [ "BuilderStage"; "EXT"; "DB" ]; + fields := + [ + ("context", Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ]); + ("handler", + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ]); + ("phantom", Ty.apply (Ty.path "core::marker::PhantomData") [ BuilderStage ]) + ]; + } *) + + (* StructTuple + { + name := "SetGenericStage"; + ty_params := []; + fields := []; + } *) + + (* StructTuple + { + name := "HandlerStage"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_default_Default_for_revm_builder_EvmBuilder_revm_builder_SetGenericStage_Tuple__revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + Definition Self : Ty.t := + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ + Ty.path "revm::builder::SetGenericStage"; + Ty.tuple []; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ]. + + (* + fn default() -> Self { + cfg_if::cfg_if! { + if #[cfg(all(feature = "optimism-default-handler", + not(feature = "negate-optimism-default-handler")))] { + let mut handler_cfg = HandlerCfg::new(SpecId::LATEST); + // set is_optimism to true by default. + handler_cfg.is_optimism = true; + + } else { + let handler_cfg = HandlerCfg::new(SpecId::LATEST); + } + } + + Self { + context: Context::default(), + handler: EvmBuilder::<'a, SetGenericStage, (), EmptyDB>::handler(handler_cfg), + phantom: PhantomData, + } + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.read (| + let~ handler_cfg := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + "new", + [] + |), + [ Value.StructTuple "revm_primitives::specification::SpecId::LATEST" [] ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::context::Context") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + [], + "default", + [] + |), + [] + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ + Ty.path "revm::builder::SetGenericStage"; + Ty.tuple []; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + "handler", + [] + |), + [ M.read (| handler_cfg |) ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_builder_EvmBuilder_revm_builder_SetGenericStage_Tuple__revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + + Module Impl_revm_builder_EvmBuilder_revm_builder_SetGenericStage_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::SetGenericStage"; EXT; DB ]. + + (* + pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, EXT, EmptyDB> { + EvmBuilder { + context: Context::new( + self.context.evm.with_db(EmptyDB::default()), + self.context.external, + ), + handler: EvmBuilder::<'a, SetGenericStage, EXT, EmptyDB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + *) + Definition with_empty_db (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::Context") + [ + EXT; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + "with_db", + [ + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ], + [], + "default", + [] + |), + [] + |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "external" + |) + |) + ] + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ + Ty.path "revm::builder::SetGenericStage"; + EXT; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + "handler", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + ] + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_empty_db : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "with_empty_db" (with_empty_db EXT DB). + + (* + pub fn with_db(self, db: ODB) -> EvmBuilder<'a, SetGenericStage, EXT, ODB> { + EvmBuilder { + context: Context::new(self.context.evm.with_db(db), self.context.external), + handler: EvmBuilder::<'a, SetGenericStage, EXT, ODB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + *) + Definition with_db (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ ODB ], [ self; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let db := M.alloc (| db |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::Context") [ EXT; ODB ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + "with_db", + [ ODB ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + |); + M.read (| db |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "external" + |) + |) + ] + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::SetGenericStage"; EXT; ODB ], + "handler", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + ] + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_db : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "with_db" (with_db EXT DB). + + (* + pub fn with_ref_db( + self, + db: ODB, + ) -> EvmBuilder<'a, SetGenericStage, EXT, WrapDatabaseRef> { + EvmBuilder { + context: Context::new( + self.context.evm.with_db(WrapDatabaseRef(db)), + self.context.external, + ), + handler: EvmBuilder::<'a, SetGenericStage, EXT, WrapDatabaseRef>::handler( + self.handler.cfg(), + ), + phantom: PhantomData, + } + } + *) + Definition with_ref_db (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ ODB ], [ self; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let db := M.alloc (| db |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::Context") + [ EXT; Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ ODB ] ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + "with_db", + [ Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ ODB ] ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + |); + Value.StructTuple "revm_primitives::db::WrapDatabaseRef" [ M.read (| db |) ] + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "external" + |) + |) + ] + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ + Ty.path "revm::builder::SetGenericStage"; + EXT; + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ ODB ] + ], + "handler", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + ] + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_ref_db : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "with_ref_db" (with_ref_db EXT DB). + + (* + pub fn with_external_context( + self, + external: OEXT, + ) -> EvmBuilder<'a, SetGenericStage, OEXT, DB> { + EvmBuilder { + context: Context::new(self.context.evm, external), + handler: EvmBuilder::<'a, SetGenericStage, OEXT, DB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + *) + Definition with_external_context (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ OEXT ], [ self; external ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let external := M.alloc (| external |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::Context") [ OEXT; DB ], + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + |); + M.read (| external |) + ] + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::SetGenericStage"; OEXT; DB ], + "handler", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + ] + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_external_context : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "with_external_context" (with_external_context EXT DB). + + (* + pub fn with_env_with_handler_cfg( + mut self, + env_with_handler_cfg: EnvWithHandlerCfg, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + let EnvWithHandlerCfg { env, handler_cfg } = env_with_handler_cfg; + self.context.evm.env = env; + EvmBuilder { + context: self.context, + handler: EvmBuilder::<'a, HandlerStage, EXT, DB>::handler(handler_cfg), + phantom: PhantomData, + } + } + *) + Definition with_env_with_handler_cfg (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; env_with_handler_cfg ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let env_with_handler_cfg := M.alloc (| env_with_handler_cfg |) in + M.read (| + M.match_operator (| + env_with_handler_cfg, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "env" + |) in + let ฮณ0_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg", + "handler_cfg" + |) in + let env := M.copy (| ฮณ0_0 |) in + let handler_cfg := M.copy (| ฮณ0_1 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |), + M.read (| env |) + |) in + M.alloc (| + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |) + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::HandlerStage"; EXT; DB ], + "handler", + [] + |), + [ M.read (| handler_cfg |) ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_env_with_handler_cfg : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "with_env_with_handler_cfg" + (with_env_with_handler_cfg EXT DB). + + (* + pub fn with_context_with_handler_cfg( + self, + context_with_handler_cfg: ContextWithHandlerCfg, + ) -> EvmBuilder<'a, HandlerStage, OEXT, ODB> { + EvmBuilder { + context: context_with_handler_cfg.context, + handler: EvmBuilder::<'a, HandlerStage, OEXT, ODB>::handler( + context_with_handler_cfg.cfg, + ), + phantom: PhantomData, + } + } + *) + Definition with_context_with_handler_cfg + (EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ OEXT; ODB ], [ self; context_with_handler_cfg ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context_with_handler_cfg := M.alloc (| context_with_handler_cfg |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.read (| + M.SubPointer.get_struct_record_field (| + context_with_handler_cfg, + "revm::context::ContextWithHandlerCfg", + "context" + |) + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::HandlerStage"; OEXT; ODB ], + "handler", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + context_with_handler_cfg, + "revm::context::ContextWithHandlerCfg", + "cfg" + |) + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_context_with_handler_cfg : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "with_context_with_handler_cfg" + (with_context_with_handler_cfg EXT DB). + + (* + pub fn with_cfg_env_with_handler_cfg( + mut self, + cfg_env_and_spec_id: CfgEnvWithHandlerCfg, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.context.evm.env.cfg = cfg_env_and_spec_id.cfg_env; + + EvmBuilder { + context: self.context, + handler: EvmBuilder::<'a, HandlerStage, EXT, DB>::handler( + cfg_env_and_spec_id.handler_cfg, + ), + phantom: PhantomData, + } + } + *) + Definition with_cfg_env_with_handler_cfg + (EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; cfg_env_and_spec_id ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let cfg_env_and_spec_id := M.alloc (| cfg_env_and_spec_id |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "cfg" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + cfg_env_and_spec_id, + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "cfg_env" + |) + |) + |) in + M.alloc (| + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |) + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::HandlerStage"; EXT; DB ], + "handler", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + cfg_env_and_spec_id, + "revm_primitives::env::handler_cfg::CfgEnvWithHandlerCfg", + "handler_cfg" + |) + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_cfg_env_with_handler_cfg : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "with_cfg_env_with_handler_cfg" + (with_cfg_env_with_handler_cfg EXT DB). + + (* + pub fn with_handler_cfg( + self, + handler_cfg: HandlerCfg, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + EvmBuilder { + context: self.context, + handler: EvmBuilder::<'a, HandlerStage, EXT, DB>::handler(handler_cfg), + phantom: PhantomData, + } + } + *) + Definition with_handler_cfg (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; handler_cfg ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let handler_cfg := M.alloc (| handler_cfg |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |) + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::HandlerStage"; EXT; DB ], + "handler", + [] + |), + [ M.read (| handler_cfg |) ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_handler_cfg : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "with_handler_cfg" (with_handler_cfg EXT DB). + End Impl_revm_builder_EvmBuilder_revm_builder_SetGenericStage_EXT_DB. + + Module Impl_revm_builder_EvmBuilder_revm_builder_HandlerStage_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::HandlerStage"; EXT; DB ]. + + (* + pub fn new(evm: Evm<'a, EXT, DB>) -> Self { + Self { + context: evm.context, + handler: evm.handler, + phantom: PhantomData, + } + } + *) + Definition new (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ evm ] => + ltac:(M.monadic + (let evm := M.alloc (| evm |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.read (| + M.SubPointer.get_struct_record_field (| evm, "revm::evm::Evm", "context" |) + |)); + ("handler", + M.read (| + M.SubPointer.get_struct_record_field (| evm, "revm::evm::Evm", "handler" |) + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "new" (new EXT DB). + + (* + pub fn reset_handler_with_empty_db(self) -> EvmBuilder<'a, HandlerStage, EXT, EmptyDB> { + EvmBuilder { + context: Context::new( + self.context.evm.with_db(EmptyDB::default()), + self.context.external, + ), + handler: EvmBuilder::<'a, HandlerStage, EXT, EmptyDB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + *) + Definition reset_handler_with_empty_db (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::Context") + [ + EXT; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + "with_db", + [ + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ], + [], + "default", + [] + |), + [] + |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "external" + |) + |) + ] + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ + Ty.path "revm::builder::HandlerStage"; + EXT; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + "handler", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + ] + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_reset_handler_with_empty_db : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "reset_handler_with_empty_db" + (reset_handler_with_empty_db EXT DB). + + (* + pub fn reset_handler_with_db( + self, + db: ODB, + ) -> EvmBuilder<'a, SetGenericStage, EXT, ODB> { + EvmBuilder { + context: Context::new(self.context.evm.with_db(db), self.context.external), + handler: EvmBuilder::<'a, SetGenericStage, EXT, ODB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + *) + Definition reset_handler_with_db (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ ODB ], [ self; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let db := M.alloc (| db |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::Context") [ EXT; ODB ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + "with_db", + [ ODB ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + |); + M.read (| db |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "external" + |) + |) + ] + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::SetGenericStage"; EXT; ODB ], + "handler", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + ] + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_reset_handler_with_db : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "reset_handler_with_db" (reset_handler_with_db EXT DB). + + (* + pub fn reset_handler_with_ref_db( + self, + db: ODB, + ) -> EvmBuilder<'a, SetGenericStage, EXT, WrapDatabaseRef> { + EvmBuilder { + context: Context::new( + self.context.evm.with_db(WrapDatabaseRef(db)), + self.context.external, + ), + handler: EvmBuilder::<'a, SetGenericStage, EXT, WrapDatabaseRef>::handler( + self.handler.cfg(), + ), + phantom: PhantomData, + } + } + *) + Definition reset_handler_with_ref_db (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ ODB ], [ self; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let db := M.alloc (| db |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::Context") + [ EXT; Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ ODB ] ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + "with_db", + [ Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ ODB ] ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + |); + Value.StructTuple "revm_primitives::db::WrapDatabaseRef" [ M.read (| db |) ] + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "external" + |) + |) + ] + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ + Ty.path "revm::builder::SetGenericStage"; + EXT; + Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ ODB ] + ], + "handler", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + ] + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_reset_handler_with_ref_db : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "reset_handler_with_ref_db" + (reset_handler_with_ref_db EXT DB). + + (* + pub fn reset_handler_with_external_context( + self, + external: OEXT, + ) -> EvmBuilder<'a, SetGenericStage, OEXT, DB> { + EvmBuilder { + context: Context::new(self.context.evm, external), + handler: EvmBuilder::<'a, SetGenericStage, OEXT, DB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + *) + Definition reset_handler_with_external_context + (EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ OEXT ], [ self; external ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let external := M.alloc (| external |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::Context") [ OEXT; DB ], + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + |); + M.read (| external |) + ] + |)); + ("handler", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::SetGenericStage"; OEXT; DB ], + "handler", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + ] + |) + ] + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_reset_handler_with_external_context : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "reset_handler_with_external_context" + (reset_handler_with_external_context EXT DB). + End Impl_revm_builder_EvmBuilder_revm_builder_HandlerStage_EXT_DB. + + Module Impl_revm_builder_EvmBuilder_BuilderStage_EXT_DB. + Definition Self (BuilderStage EXT DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::builder::EvmBuilder") [ BuilderStage; EXT; DB ]. + + (* + fn handler(handler_cfg: HandlerCfg) -> Handler<'a, Evm<'a, EXT, DB>, EXT, DB> { + Handler::new(handler_cfg) + } + *) + Definition handler (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ handler_cfg ] => + ltac:(M.monadic + (let handler_cfg := M.alloc (| handler_cfg |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "new", + [] + |), + [ M.read (| handler_cfg |) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_handler : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction (Self BuilderStage EXT DB) "handler" (handler BuilderStage EXT DB). + + (* + pub fn with_handler( + self, + handler: Handler<'a, Evm<'a, EXT, DB>, EXT, DB>, + ) -> EvmBuilder<'a, BuilderStage, EXT, DB> { + EvmBuilder { + context: self.context, + handler, + phantom: PhantomData, + } + } + *) + Definition with_handler (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self; handler ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let handler := M.alloc (| handler |) in + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |) + |)); + ("handler", M.read (| handler |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_handler : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "with_handler" + (with_handler BuilderStage EXT DB). + + (* + pub fn build(self) -> Evm<'a, EXT, DB> { + Evm::new(self.context, self.handler) + } + *) + Definition build (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_build : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction (Self BuilderStage EXT DB) "build" (build BuilderStage EXT DB). + + (* + pub fn append_handler_register( + mut self, + handle_register: register::HandleRegister, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.handler + .append_handler_register(register::HandleRegisters::Plain(handle_register)); + EvmBuilder { + context: self.context, + handler: self.handler, + + phantom: PhantomData, + } + } + *) + Definition append_handler_register + (BuilderStage EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self; handle_register ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let handle_register := M.alloc (| handle_register |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "append_handler_register", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |); + Value.StructTuple + "revm::handler::register::HandleRegisters::Plain" + [ M.read (| handle_register |) ] + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |) + |)); + ("handler", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_append_handler_register : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "append_handler_register" + (append_handler_register BuilderStage EXT DB). + + (* + pub fn append_handler_register_box( + mut self, + handle_register: register::HandleRegisterBox, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.handler + .append_handler_register(register::HandleRegisters::Box(handle_register)); + EvmBuilder { + context: self.context, + handler: self.handler, + + phantom: PhantomData, + } + } + *) + Definition append_handler_register_box + (BuilderStage EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self; handle_register ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let handle_register := M.alloc (| handle_register |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "append_handler_register", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |); + Value.StructTuple + "revm::handler::register::HandleRegisters::Box" + [ (* Unsize *) M.pointer_coercion (M.read (| handle_register |)) ] + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |) + |)); + ("handler", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_append_handler_register_box : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "append_handler_register_box" + (append_handler_register_box BuilderStage EXT DB). + + (* + pub fn with_spec_id(mut self, spec_id: SpecId) -> Self { + self.handler.modify_spec_id(spec_id); + EvmBuilder { + context: self.context, + handler: self.handler, + + phantom: PhantomData, + } + } + *) + Definition with_spec_id (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self; spec_id ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let spec_id := M.alloc (| spec_id |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "modify_spec_id", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |); + M.read (| spec_id |) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::builder::EvmBuilder" + [ + ("context", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |) + |)); + ("handler", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + |)); + ("phantom", Value.StructTuple "core::marker::PhantomData" []) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_spec_id : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "with_spec_id" + (with_spec_id BuilderStage EXT DB). + + (* + pub fn modify_db(mut self, f: impl FnOnce(&mut DB)) -> Self { + f(&mut self.context.evm.db); + self + } + *) + Definition modify_db (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [ impl_FnOnce__mut_DB_ ], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnOnce", + impl_FnOnce__mut_DB_, + [ Ty.tuple [ Ty.apply (Ty.path "&mut") [ DB ] ] ], + "call_once", + [] + |), + [ + M.read (| f |); + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_modify_db : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction (Self BuilderStage EXT DB) "modify_db" (modify_db BuilderStage EXT DB). + + (* + pub fn modify_external_context(mut self, f: impl FnOnce(&mut EXT)) -> Self { + f(&mut self.context.external); + self + } + *) + Definition modify_external_context + (BuilderStage EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [ impl_FnOnce__mut_EXT_ ], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnOnce", + impl_FnOnce__mut_EXT_, + [ Ty.tuple [ Ty.apply (Ty.path "&mut") [ EXT ] ] ], + "call_once", + [] + |), + [ + M.read (| f |); + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "external" + |) + ] + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_modify_external_context : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "modify_external_context" + (modify_external_context BuilderStage EXT DB). + + (* + pub fn modify_env(mut self, f: impl FnOnce(&mut Box)) -> Self { + f(&mut self.context.evm.env); + self + } + *) + Definition modify_env (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [ impl_FnOnce__mut_Box_Env__ ], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnOnce", + impl_FnOnce__mut_Box_Env__, + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_primitives::env::Env"; + Ty.path "alloc::alloc::Global" + ] + ] + ] + ], + "call_once", + [] + |), + [ + M.read (| f |); + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + ] + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_modify_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "modify_env" + (modify_env BuilderStage EXT DB). + + (* + pub fn with_env(mut self, env: Box) -> Self { + self.context.evm.env = env; + self + } + *) + Definition with_env (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self; env ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let env := M.alloc (| env |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |), + M.read (| env |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction (Self BuilderStage EXT DB) "with_env" (with_env BuilderStage EXT DB). + + (* + pub fn modify_tx_env(mut self, f: impl FnOnce(&mut TxEnv)) -> Self { + f(&mut self.context.evm.env.tx); + self + } + *) + Definition modify_tx_env (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [ impl_FnOnce__mut_TxEnv_ ], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnOnce", + impl_FnOnce__mut_TxEnv_, + [ + Ty.tuple + [ Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::env::TxEnv" ] ] + ], + "call_once", + [] + |), + [ + M.read (| f |); + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |) + ] + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_modify_tx_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "modify_tx_env" + (modify_tx_env BuilderStage EXT DB). + + (* + pub fn with_tx_env(mut self, tx_env: TxEnv) -> Self { + self.context.evm.env.tx = tx_env; + self + } + *) + Definition with_tx_env (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self; tx_env ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let tx_env := M.alloc (| tx_env |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |), + M.read (| tx_env |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_tx_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "with_tx_env" + (with_tx_env BuilderStage EXT DB). + + (* + pub fn modify_block_env(mut self, f: impl FnOnce(&mut BlockEnv)) -> Self { + f(&mut self.context.evm.env.block); + self + } + *) + Definition modify_block_env + (BuilderStage EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [ impl_FnOnce__mut_BlockEnv_ ], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnOnce", + impl_FnOnce__mut_BlockEnv_, + [ + Ty.tuple + [ Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::env::BlockEnv" ] ] + ], + "call_once", + [] + |), + [ + M.read (| f |); + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "block" + |) + ] + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_modify_block_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "modify_block_env" + (modify_block_env BuilderStage EXT DB). + + (* + pub fn with_block_env(mut self, block_env: BlockEnv) -> Self { + self.context.evm.env.block = block_env; + self + } + *) + Definition with_block_env (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self; block_env ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let block_env := M.alloc (| block_env |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "block" + |), + M.read (| block_env |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_block_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "with_block_env" + (with_block_env BuilderStage EXT DB). + + (* + pub fn modify_cfg_env(mut self, f: impl FnOnce(&mut CfgEnv)) -> Self { + f(&mut self.context.evm.env.cfg); + self + } + *) + Definition modify_cfg_env (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [ impl_FnOnce__mut_CfgEnv_ ], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnOnce", + impl_FnOnce__mut_CfgEnv_, + [ + Ty.tuple + [ Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::env::CfgEnv" ] ] + ], + "call_once", + [] + |), + [ + M.read (| f |); + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "cfg" + |) + ] + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_modify_cfg_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "modify_cfg_env" + (modify_cfg_env BuilderStage EXT DB). + + (* + pub fn with_clear_env(mut self) -> Self { + self.context.evm.env.clear(); + self + } + *) + Definition with_clear_env (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "revm_primitives::env::Env", "clear", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_clear_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "with_clear_env" + (with_clear_env BuilderStage EXT DB). + + (* + pub fn with_clear_tx_env(mut self) -> Self { + self.context.evm.env.tx.clear(); + self + } + *) + Definition with_clear_tx_env + (BuilderStage EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::TxEnv", + "clear", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_clear_tx_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "with_clear_tx_env" + (with_clear_tx_env BuilderStage EXT DB). + + (* + pub fn with_clear_block_env(mut self) -> Self { + self.context.evm.env.block.clear(); + self + } + *) + Definition with_clear_block_env + (BuilderStage EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::BlockEnv", + "clear", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "block" + |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_clear_block_env : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "with_clear_block_env" + (with_clear_block_env BuilderStage EXT DB). + + (* + pub fn reset_handler(mut self) -> Self { + self.handler = Self::handler(self.handler.cfg()); + self + } + *) + Definition reset_handler (BuilderStage EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self BuilderStage EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::builder::EvmBuilder") [ BuilderStage; EXT; DB ], + "handler", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::builder::EvmBuilder", + "handler" + |) + ] + |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_reset_handler : + forall (BuilderStage EXT DB : Ty.t), + M.IsAssociatedFunction + (Self BuilderStage EXT DB) + "reset_handler" + (reset_handler BuilderStage EXT DB). + End Impl_revm_builder_EvmBuilder_BuilderStage_EXT_DB. +End builder. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context.md new file mode 100644 index 00000000..94a4307f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context.md @@ -0,0 +1,367 @@ +# ๐Ÿ“ context.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/context.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module context. + (* StructRecord + { + name := "Context"; + ty_params := [ "EXT"; "DB" ]; + fields := + [ + ("evm", Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ]); + ("external", EXT) + ]; + } *) + + Module Impl_core_clone_Clone_where_core_clone_Clone_EXT_where_revm_primitives_db_Database_DB_where_core_clone_Clone_DB_where_core_clone_Clone_associated_type_for_revm_context_Context_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ]. + + (* + fn clone(&self) -> Self { + Self { + evm: self.evm.clone(), + external: self.external.clone(), + } + } + *) + Definition clone (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::context::Context" + [ + ("evm", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::Context", + "evm" + |) + ] + |)); + ("external", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", EXT, [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::Context", + "external" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (EXT DB : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self EXT DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone EXT DB)) ]. + End Impl_core_clone_Clone_where_core_clone_Clone_EXT_where_revm_primitives_db_Database_DB_where_core_clone_Clone_DB_where_core_clone_Clone_associated_type_for_revm_context_Context_EXT_DB. + + Module Impl_core_default_Default_for_revm_context_Context_Tuple__revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + Definition Self : Ty.t := + Ty.apply + (Ty.path "revm::context::Context") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ]. + + (* + fn default() -> Self { + Self::new_empty() + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::Context") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + "new_empty", + [] + |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_context_Context_Tuple__revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + + Module Impl_revm_context_Context_Tuple__revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + Definition Self : Ty.t := + Ty.apply + (Ty.path "revm::context::Context") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ]. + + (* + pub fn new_empty() -> Context<(), EmptyDB> { + Context { + evm: EvmContext::new(EmptyDB::new()), + external: (), + } + } + *) + Definition new_empty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::context::Context" + [ + ("evm", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ], + "new", + [] + |), + [] + |) + ] + |)); + ("external", Value.Tuple []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_empty : M.IsAssociatedFunction Self "new_empty" new_empty. + End Impl_revm_context_Context_Tuple__revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + + Module Impl_revm_context_Context_Tuple__DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::Context") [ Ty.tuple []; DB ]. + + (* + pub fn new_with_db(db: DB) -> Context<(), DB> { + Context { + evm: EvmContext::new_with_env(db, Box::default()), + external: (), + } + } + *) + Definition new_with_db (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ db ] => + ltac:(M.monadic + (let db := M.alloc (| db |) in + Value.StructRecord + "revm::context::Context" + [ + ("evm", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + "new_with_env", + [] + |), + [ + M.read (| db |); + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ], + [], + "default", + [] + |), + [] + |) + ] + |)); + ("external", Value.Tuple []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_with_db : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "new_with_db" (new_with_db DB). + End Impl_revm_context_Context_Tuple__DB. + + Module Impl_revm_context_Context_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ]. + + (* + pub fn new(evm: EvmContext, external: EXT) -> Context { + Context { evm, external } + } + *) + Definition new (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ evm; external ] => + ltac:(M.monadic + (let evm := M.alloc (| evm |) in + let external := M.alloc (| external |) in + Value.StructRecord + "revm::context::Context" + [ ("evm", M.read (| evm |)); ("external", M.read (| external |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "new" (new EXT DB). + End Impl_revm_context_Context_EXT_DB. + + (* StructRecord + { + name := "ContextWithHandlerCfg"; + ty_params := [ "EXT"; "DB" ]; + fields := + [ + ("context", Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ]); + ("cfg", Ty.path "revm_primitives::env::handler_cfg::HandlerCfg") + ]; + } *) + + Module Impl_revm_context_ContextWithHandlerCfg_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::ContextWithHandlerCfg") [ EXT; DB ]. + + (* + pub fn new(context: Context, cfg: HandlerCfg) -> Self { + Self { cfg, context } + } + *) + Definition new (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ context; cfg ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let cfg := M.alloc (| cfg |) in + Value.StructRecord + "revm::context::ContextWithHandlerCfg" + [ ("cfg", M.read (| cfg |)); ("context", M.read (| context |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "new" (new EXT DB). + End Impl_revm_context_ContextWithHandlerCfg_EXT_DB. + + Module Impl_core_clone_Clone_where_core_clone_Clone_EXT_where_revm_primitives_db_Database_DB_where_core_clone_Clone_DB_where_core_clone_Clone_associated_type_for_revm_context_ContextWithHandlerCfg_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::ContextWithHandlerCfg") [ EXT; DB ]. + + (* + fn clone(&self) -> Self { + Self { + context: self.context.clone(), + cfg: self.cfg, + } + } + *) + Definition clone (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::context::ContextWithHandlerCfg" + [ + ("context", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::ContextWithHandlerCfg", + "context" + |) + ] + |)); + ("cfg", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::ContextWithHandlerCfg", + "cfg" + |) + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (EXT DB : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self EXT DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone EXT DB)) ]. + End Impl_core_clone_Clone_where_core_clone_Clone_EXT_where_revm_primitives_db_Database_DB_where_core_clone_Clone_DB_where_core_clone_Clone_associated_type_for_revm_context_ContextWithHandlerCfg_EXT_DB. +End context. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/context_precompiles.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/context_precompiles.md new file mode 100644 index 00000000..543134a3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/context_precompiles.md @@ -0,0 +1,1309 @@ +# ๐Ÿ“ context_precompiles.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/context/context_precompiles.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module context. + Module context_precompiles. + (* + Enum ContextPrecompile + { + ty_params := [ "DB" ]; + variants := + [ + { + name := "Ordinary"; + item := StructTuple [ Ty.path "revm_primitives::precompile::Precompile" ]; + discriminant := None; + }; + { + name := "ContextStateful"; + item := + StructTuple + [ + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("revm::context::context_precompiles::ContextStatefulPrecompile::Trait", + []) + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + discriminant := None; + }; + { + name := "ContextStatefulMut"; + item := + StructTuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("revm::context::context_precompiles::ContextStatefulPrecompileMut::Trait", + []) + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompile_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompile") [ DB ]. + + (* + fn clone(&self) -> Self { + match self { + Self::Ordinary(arg0) => Self::Ordinary(arg0.clone()), + Self::ContextStateful(arg0) => Self::ContextStateful(arg0.clone()), + Self::ContextStatefulMut(arg0) => Self::ContextStatefulMut(arg0.clone()), + } + } + *) + Definition clone (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::context::context_precompiles::ContextPrecompile::Ordinary", + 0 + |) in + let arg0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm::context::context_precompiles::ContextPrecompile::Ordinary" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::precompile::Precompile", + [], + "clone", + [] + |), + [ M.read (| arg0 |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::context::context_precompiles::ContextPrecompile::ContextStateful", + 0 + |) in + let arg0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm::context::context_precompiles::ContextPrecompile::ContextStateful" + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("revm::context::context_precompiles::ContextStatefulPrecompile::Trait", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ M.read (| arg0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::context::context_precompiles::ContextPrecompile::ContextStatefulMut", + 0 + |) in + let arg0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm::context::context_precompiles::ContextPrecompile::ContextStatefulMut" + [ + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("revm::context::context_precompiles::ContextStatefulPrecompileMut::Trait", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ M.read (| arg0 |) ] + |)) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone DB)) ]. + End Impl_core_clone_Clone_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompile_DB. + + (* StructRecord + { + name := "ContextPrecompiles"; + ty_params := [ "DB" ]; + fields := + [ + ("inner", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompile") [ DB ]; + Ty.path "std::hash::random::RandomState" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_where_core_clone_Clone_DB_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompiles_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompiles") [ DB ]. + + (* Clone *) + Definition clone (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::context::context_precompiles::ContextPrecompiles" + [ + ("inner", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ]; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::context_precompiles::ContextPrecompiles", + "inner" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone DB)) ]. + End Impl_core_clone_Clone_where_core_clone_Clone_DB_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompiles_DB. + + Module Impl_revm_context_context_precompiles_ContextPrecompiles_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompiles") [ DB ]. + + (* + pub fn addresses(&self) -> impl Iterator { + self.inner.keys() + } + *) + Definition addresses (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ]; + Ty.path "std::hash::random::RandomState" + ], + "keys", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::context_precompiles::ContextPrecompiles", + "inner" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_addresses : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "addresses" (addresses DB). + + (* + pub fn extend( + &mut self, + other: impl IntoIterator)>>, + ) { + self.inner.extend(other.into_iter().map(Into::into)); + } + *) + Definition extend (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ + impl_Into__Address__ContextPrecompile_DB___; + impl_IntoIterator_Item___impl_Into__Address__ContextPrecompile_DB____ + ], + [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::Extend", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ]; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ] + ], + "extend", + [ + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.associated; + Ty.function + [ impl_Into__Address__ContextPrecompile_DB___ ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ]) + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::context_precompiles::ContextPrecompiles", + "inner" + |); + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "map", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ]; + Ty.function + [ impl_Into__Address__ContextPrecompile_DB___ ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + impl_IntoIterator_Item___impl_Into__Address__ContextPrecompile_DB____, + [], + "into_iter", + [] + |), + [ M.read (| other |) ] + |); + M.get_trait_method (| + "core::convert::Into", + impl_Into__Address__ContextPrecompile_DB___, + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ] + ], + "into", + [] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_extend : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "extend" (extend DB). + + (* + pub fn call( + &mut self, + addess: Address, + bytes: &Bytes, + gas_price: u64, + evmctx: &mut InnerEvmContext, + ) -> Option { + let precompile = self.inner.get_mut(&addess)?; + + match precompile { + ContextPrecompile::Ordinary(p) => Some(p.call(bytes, gas_price, &evmctx.env)), + ContextPrecompile::ContextStatefulMut(p) => Some(p.call_mut(bytes, gas_price, evmctx)), + ContextPrecompile::ContextStateful(p) => Some(p.call(bytes, gas_price, evmctx)), + } + } + *) + Definition call (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; addess; bytes; gas_price; evmctx ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let addess := M.alloc (| addess |) in + let bytes := M.alloc (| bytes |) in + let gas_price := M.alloc (| gas_price |) in + let evmctx := M.alloc (| evmctx |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ precompile := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompile") + [ DB ]; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::context_precompiles::ContextPrecompiles", + "inner" + |); + addess + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bytes_::Bytes" + ]; + Ty.path + "revm_primitives::precompile::PrecompileError" + ] + ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "core::convert::Infallible" ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.match_operator (| + precompile, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::context::context_precompiles::ContextPrecompile::Ordinary", + 0 + |) in + let p := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::precompile::Precompile", + "call", + [] + |), + [ + M.read (| p |); + M.read (| bytes |); + M.read (| gas_price |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| evmctx |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::context::context_precompiles::ContextPrecompile::ContextStatefulMut", + 0 + |) in + let p := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_trait_method (| + "revm::context::context_precompiles::ContextStatefulPrecompileMut", + Ty.dyn + [ + ("revm::context::context_precompiles::ContextStatefulPrecompileMut::Trait", + []) + ], + [ DB ], + "call_mut", + [] + |), + [ + M.read (| M.read (| p |) |); + M.read (| bytes |); + M.read (| gas_price |); + M.read (| evmctx |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::context::context_precompiles::ContextPrecompile::ContextStateful", + 0 + |) in + let p := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_trait_method (| + "revm::context::context_precompiles::ContextStatefulPrecompile", + Ty.dyn + [ + ("revm::context::context_precompiles::ContextStatefulPrecompile::Trait", + []) + ], + [ DB ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("revm::context::context_precompiles::ContextStatefulPrecompile::Trait", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ M.read (| p |) ] + |); + M.read (| bytes |); + M.read (| gas_price |); + M.read (| evmctx |) + ] + |) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_call : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "call" (call DB). + End Impl_revm_context_context_precompiles_ContextPrecompiles_DB. + + Module Impl_core_default_Default_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompiles_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompiles") [ DB ]. + + (* + fn default() -> Self { + Self { + inner: Default::default(), + } + } + *) + Definition default (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::context::context_precompiles::ContextPrecompiles" + [ + ("inner", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ]; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::default::Default" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method (default DB)) ]. + End Impl_core_default_Default_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompiles_DB. + + Module Impl_core_ops_deref_Deref_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompiles_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompiles") [ DB ]. + + (* type Target = HashMap>; *) + Definition _Target (DB : Ty.t) : Ty.t := + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompile") [ DB ]; + Ty.path "std::hash::random::RandomState" + ]. + + (* + fn deref(&self) -> &Self::Target { + &self.inner + } + *) + Definition deref (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::context_precompiles::ContextPrecompiles", + "inner" + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::ops::deref::Deref" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) + [ ("Target", InstanceField.Ty (_Target DB)); ("deref", InstanceField.Method (deref DB)) ]. + End Impl_core_ops_deref_Deref_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompiles_DB. + + Module Impl_core_ops_deref_DerefMut_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompiles_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompiles") [ DB ]. + + (* + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } + *) + Definition deref_mut (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::context_precompiles::ContextPrecompiles", + "inner" + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::ops::deref::DerefMut" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("deref_mut", InstanceField.Method (deref_mut DB)) ]. + End Impl_core_ops_deref_DerefMut_where_revm_primitives_db_Database_DB_for_revm_context_context_precompiles_ContextPrecompiles_DB. + + (* Trait *) + (* Empty module 'ContextStatefulPrecompile' *) + + (* Trait *) + (* Empty module 'ContextStatefulPrecompileMut' *) + + Axiom ContextStatefulPrecompileArc : + forall (DB : Ty.t), + (Ty.apply + (Ty.path "revm::context::context_precompiles::ContextStatefulPrecompileArc") + [ DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn [ ("revm::context::context_precompiles::ContextStatefulPrecompile::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom ContextStatefulPrecompileBox : + forall (DB : Ty.t), + (Ty.apply + (Ty.path "revm::context::context_precompiles::ContextStatefulPrecompileBox") + [ DB ]) = + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ ("revm::context::context_precompiles::ContextStatefulPrecompileMut::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ]). + + Module Impl_core_convert_From_where_revm_primitives_db_Database_DB_revm_primitives_precompile_Precompile_for_revm_context_context_precompiles_ContextPrecompile_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompile") [ DB ]. + + (* + fn from(p: Precompile) -> Self { + ContextPrecompile::Ordinary(p) + } + *) + Definition from (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ p ] => + ltac:(M.monadic + (let p := M.alloc (| p |) in + Value.StructTuple + "revm::context::context_precompiles::ContextPrecompile::Ordinary" + [ M.read (| p |) ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::convert::From" + (Self DB) + (* Trait polymorphic types *) + [ (* T *) Ty.path "revm_primitives::precompile::Precompile" ] + (* Instance *) [ ("from", InstanceField.Method (from DB)) ]. + End Impl_core_convert_From_where_revm_primitives_db_Database_DB_revm_primitives_precompile_Precompile_for_revm_context_context_precompiles_ContextPrecompile_DB. + + Module Impl_core_convert_From_where_revm_primitives_db_Database_DB_revm_precompile_Precompiles_for_revm_context_context_precompiles_ContextPrecompiles_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompiles") [ DB ]. + + (* + fn from(p: Precompiles) -> Self { + ContextPrecompiles { + inner: p.inner.into_iter().map(|(k, v)| (k, v.into())).collect(), + } + } + *) + Definition from (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ p ] => + ltac:(M.monadic + (let p := M.alloc (| p |) in + Value.StructRecord + "revm::context::context_precompiles::ContextPrecompiles" + [ + ("inner", + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ] + ] + ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ]; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ], + [], + "map", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ] + ] + ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + p, + "revm_precompile::Precompiles", + "inner" + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let k := M.copy (| ฮณ0_0 |) in + let v := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| k |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "revm_primitives::precompile::Precompile", + [ + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ], + "into", + [] + |), + [ M.read (| v |) ] + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::convert::From" + (Self DB) + (* Trait polymorphic types *) [ (* T *) Ty.path "revm_precompile::Precompiles" ] + (* Instance *) [ ("from", InstanceField.Method (from DB)) ]. + End Impl_core_convert_From_where_revm_primitives_db_Database_DB_revm_precompile_Precompiles_for_revm_context_context_precompiles_ContextPrecompiles_DB. + + Module Impl_core_convert_From_where_revm_primitives_db_Database_DB_ref__revm_precompile_Precompiles_for_revm_context_context_precompiles_ContextPrecompiles_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompiles") [ DB ]. + + (* + fn from(p: &Precompiles) -> Self { + ContextPrecompiles { + inner: p + .inner + .iter() + .map(|(&k, v)| (k, v.clone().into())) + .collect(), + } + } + *) + Definition from (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ p ] => + ltac:(M.monadic + (let p := M.alloc (| p |) in + Value.StructRecord + "revm::context::context_precompiles::ContextPrecompiles" + [ + ("inner", + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::precompile::Precompile" ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ]; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile" + ], + [], + "map", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::precompile::Precompile" ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::precompile::Precompile"; + Ty.path "std::hash::random::RandomState" + ], + "iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| p |), + "revm_precompile::Precompiles", + "inner" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let k := M.copy (| ฮณ0_0 |) in + let v := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| k |); + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "revm_primitives::precompile::Precompile", + [ + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompile") + [ DB ] + ], + "into", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm_primitives::precompile::Precompile", + [], + "clone", + [] + |), + [ M.read (| v |) ] + |) + ] + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::convert::From" + (Self DB) + (* Trait polymorphic types *) + [ (* T *) Ty.apply (Ty.path "&") [ Ty.path "revm_precompile::Precompiles" ] ] + (* Instance *) [ ("from", InstanceField.Method (from DB)) ]. + End Impl_core_convert_From_where_revm_primitives_db_Database_DB_ref__revm_precompile_Precompiles_for_revm_context_context_precompiles_ContextPrecompiles_DB. + End context_precompiles. +End context. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/evm_context.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/evm_context.md new file mode 100644 index 00000000..4bf09228 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/evm_context.md @@ -0,0 +1,2150 @@ +# ๐Ÿ“ evm_context.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/context/evm_context.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module context. + Module evm_context. + (* StructRecord + { + name := "EvmContext"; + ty_params := [ "DB" ]; + fields := + [ + ("inner", + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ]); + ("precompiles", + Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompiles") [ DB ]) + ]; + } *) + + Module Impl_core_clone_Clone_where_revm_primitives_db_Database_DB_where_core_clone_Clone_DB_where_core_clone_Clone_associated_type_for_revm_context_evm_context_EvmContext_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ]. + + (* + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + precompiles: ContextPrecompiles::default(), + } + } + *) + Definition clone (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::context::evm_context::EvmContext" + [ + ("inner", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |) + ] + |)); + ("precompiles", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompiles") + [ DB ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone DB)) ]. + End Impl_core_clone_Clone_where_revm_primitives_db_Database_DB_where_core_clone_Clone_DB_where_core_clone_Clone_associated_type_for_revm_context_evm_context_EvmContext_DB. + + Module Impl_core_fmt_Debug_where_revm_primitives_db_Database_DB_where_core_fmt_Debug_DB_where_core_fmt_Debug_associated_type_for_revm_context_evm_context_EvmContext_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ]. + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EvmContext") + .field("inner", &self.inner) + .field("precompiles", &self.inner) + .finish_non_exhaustive() + } + *) + Definition fmt (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "finish_non_exhaustive", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct", + [] + |), + [ M.read (| f |); M.read (| Value.String "EvmContext" |) ] + |) + |); + M.read (| Value.String "inner" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |)) + ] + |); + M.read (| Value.String "precompiles" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt DB)) ]. + End Impl_core_fmt_Debug_where_revm_primitives_db_Database_DB_where_core_fmt_Debug_DB_where_core_fmt_Debug_associated_type_for_revm_context_evm_context_EvmContext_DB. + + Module Impl_core_ops_deref_Deref_where_revm_primitives_db_Database_DB_for_revm_context_evm_context_EvmContext_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ]. + + (* type Target = InnerEvmContext; *) + Definition _Target (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ]. + + (* + fn deref(&self) -> &Self::Target { + &self.inner + } + *) + Definition deref (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::ops::deref::Deref" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) + [ ("Target", InstanceField.Ty (_Target DB)); ("deref", InstanceField.Method (deref DB)) ]. + End Impl_core_ops_deref_Deref_where_revm_primitives_db_Database_DB_for_revm_context_evm_context_EvmContext_DB. + + Module Impl_core_ops_deref_DerefMut_where_revm_primitives_db_Database_DB_for_revm_context_evm_context_EvmContext_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ]. + + (* + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } + *) + Definition deref_mut (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::ops::deref::DerefMut" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("deref_mut", InstanceField.Method (deref_mut DB)) ]. + End Impl_core_ops_deref_DerefMut_where_revm_primitives_db_Database_DB_for_revm_context_evm_context_EvmContext_DB. + + Module Impl_revm_context_evm_context_EvmContext_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ]. + + (* + pub fn new(db: DB) -> Self { + Self { + inner: InnerEvmContext::new(db), + precompiles: ContextPrecompiles::default(), + } + } + *) + Definition new (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ db ] => + ltac:(M.monadic + (let db := M.alloc (| db |) in + Value.StructRecord + "revm::context::evm_context::EvmContext" + [ + ("inner", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "new", + [] + |), + [ M.read (| db |) ] + |)); + ("precompiles", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompiles") + [ DB ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "new" (new DB). + + (* + pub fn new_with_env(db: DB, env: Box) -> Self { + Self { + inner: InnerEvmContext::new_with_env(db, env), + precompiles: ContextPrecompiles::default(), + } + } + *) + Definition new_with_env (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ db; env ] => + ltac:(M.monadic + (let db := M.alloc (| db |) in + let env := M.alloc (| env |) in + Value.StructRecord + "revm::context::evm_context::EvmContext" + [ + ("inner", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "new_with_env", + [] + |), + [ M.read (| db |); M.read (| env |) ] + |)); + ("precompiles", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompiles") + [ DB ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_with_env : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "new_with_env" (new_with_env DB). + + (* + pub fn with_db(self, db: ODB) -> EvmContext { + EvmContext { + inner: self.inner.with_db(db), + precompiles: ContextPrecompiles::default(), + } + } + *) + Definition with_db (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ ODB ], [ self; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let db := M.alloc (| db |) in + Value.StructRecord + "revm::context::evm_context::EvmContext" + [ + ("inner", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "with_db", + [ ODB ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::context::evm_context::EvmContext", + "inner" + |) + |); + M.read (| db |) + ] + |)); + ("precompiles", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompiles") + [ ODB ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_db : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "with_db" (with_db DB). + + (* + pub fn set_precompiles(&mut self, precompiles: ContextPrecompiles) { + // set warm loaded addresses. + self.journaled_state.warm_preloaded_addresses = + precompiles.addresses().copied().collect::>(); + self.precompiles = precompiles; + } + *) + Definition set_precompiles (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; precompiles ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let precompiles := M.alloc (| precompiles |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ M.read (| self |) ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |), + "revm::journaled_state::JournaledState", + "warm_preloaded_addresses" + |), + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply (Ty.path "core::iter::adapters::copied::Copied") [ Ty.associated ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "copied", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompiles") + [ DB ], + "addresses", + [] + |), + [ precompiles ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "precompiles" + |), + M.read (| precompiles |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_precompiles : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "set_precompiles" (set_precompiles DB). + + (* + fn call_precompile( + &mut self, + address: Address, + input_data: &Bytes, + gas: Gas, + ) -> Option { + let out = self + .precompiles + .call(address, input_data, gas.limit(), &mut self.inner)?; + + let mut result = InterpreterResult { + result: InstructionResult::Return, + gas, + output: Bytes::new(), + }; + + match out { + Ok((gas_used, data)) => { + if result.gas.record_cost(gas_used) { + result.result = InstructionResult::Return; + result.output = data; + } else { + result.result = InstructionResult::PrecompileOOG; + } + } + Err(e) => { + result.result = if e == crate::precompile::Error::OutOfGas { + InstructionResult::PrecompileOOG + } else { + InstructionResult::PrecompileError + }; + } + } + Some(result) + } + *) + Definition call_precompile (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address; input_data; gas ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let input_data := M.alloc (| input_data |) in + let gas := M.alloc (| gas |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ out := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bytes_::Bytes" + ]; + Ty.path "revm_primitives::precompile::PrecompileError" + ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::context::context_precompiles::ContextPrecompiles") + [ DB ], + "call", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "precompiles" + |); + M.read (| address |); + M.read (| input_data |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "limit", + [] + |), + [ gas ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_interpreter::interpreter::InterpreterResult" + ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "core::convert::Infallible" ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ result := + M.alloc (| + Value.StructRecord + "revm_interpreter::interpreter::InterpreterResult" + [ + ("result", + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Return" + []); + ("gas", M.read (| gas |)); + ("output", + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |)) + ] + |) in + let~ _ := + M.match_operator (| + out, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let gas_used := M.copy (| ฮณ1_0 |) in + let data := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + result, + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |); + M.read (| gas_used |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + result, + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Return" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + result, + "revm_interpreter::interpreter::InterpreterResult", + "output" + |), + M.read (| data |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + result, + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::PrecompileOOG" + [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + result, + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "revm_primitives::precompile::PrecompileError", + [ + Ty.path + "revm_primitives::precompile::PrecompileError" + ], + "eq", + [] + |), + [ + e; + M.alloc (| + Value.StructTuple + "revm_primitives::precompile::PrecompileError::OutOfGas" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::PrecompileOOG" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::PrecompileError" + [] + |))) + ] + |) + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| result |) ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_call_precompile : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "call_precompile" (call_precompile DB). + + (* + pub fn make_call_frame( + &mut self, + inputs: &CallInputs, + ) -> Result> { + let gas = Gas::new(inputs.gas_limit); + + let return_result = |instruction_result: InstructionResult| { + Ok(FrameOrResult::new_call_result( + InterpreterResult { + result: instruction_result, + gas, + output: Bytes::new(), + }, + inputs.return_memory_offset.clone(), + )) + }; + + // Check depth + if self.journaled_state.depth() > CALL_STACK_LIMIT { + return return_result(InstructionResult::CallTooDeep); + } + + let (account, _) = self + .inner + .journaled_state + .load_code(inputs.bytecode_address, &mut self.inner.db)?; + let code_hash = account.info.code_hash(); + let bytecode = account.info.code.clone().unwrap_or_default(); + + // Create subroutine checkpoint + let checkpoint = self.journaled_state.checkpoint(); + + // Touch address. For "EIP-158 State Clear", this will erase empty accounts. + match inputs.value { + // if transfer value is zero, do the touch. + CallValue::Transfer(value) if value == U256::ZERO => { + self.load_account(inputs.target_address)?; + self.journaled_state.touch(&inputs.target_address); + } + CallValue::Transfer(value) => { + // Transfer value from caller to called account + if let Some(result) = self.inner.journaled_state.transfer( + &inputs.caller, + &inputs.target_address, + value, + &mut self.inner.db, + )? { + self.journaled_state.checkpoint_revert(checkpoint); + return return_result(result); + } + } + _ => {} + }; + + if let Some(result) = self.call_precompile(inputs.bytecode_address, &inputs.input, gas) { + if matches!(result.result, return_ok!()) { + self.journaled_state.checkpoint_commit(); + } else { + self.journaled_state.checkpoint_revert(checkpoint); + } + Ok(FrameOrResult::new_call_result( + result, + inputs.return_memory_offset.clone(), + )) + } else if !bytecode.is_empty() { + let contract = + Contract::new_with_context(inputs.input.clone(), bytecode, Some(code_hash), inputs); + // Create interpreter and executes call and push new CallStackFrame. + Ok(FrameOrResult::new_call_frame( + inputs.return_memory_offset.clone(), + checkpoint, + Interpreter::new(contract, gas.limit(), inputs.is_static), + )) + } else { + self.journaled_state.checkpoint_commit(); + return_result(InstructionResult::Stop) + } + } + *) + Definition make_call_frame (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let inputs := M.alloc (| inputs |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ gas := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "gas_limit" + |) + |) + ] + |) + |) in + let~ return_result := + M.alloc (| + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let instruction_result := M.copy (| ฮณ |) in + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameOrResult", + "new_call_result", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter::InterpreterResult" + [ + ("result", M.read (| instruction_result |)); + ("gas", M.read (| gas |)); + ("output", + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |)) + ]; + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "return_memory_offset" + |) + ] + |) + ] + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "depth", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ M.read (| self |) ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |)) + (M.read (| + M.get_constant (| "revm::evm::CALL_STACK_LIMIT" |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ + return_result; + Value.Tuple + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + [] + ] + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_code", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "bytecode_address" + |) + |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let account := M.copy (| ฮณ0_0 |) in + let~ code_hash := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "code_hash", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |) + ] + |) + |) in + let~ bytecode := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::bytecode::Bytecode" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::bytecode::Bytecode" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code" + |) + ] + |) + ] + |) + |) in + let~ checkpoint := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ M.read (| self |) ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + let value := M.copy (| ฮณ0_0 |) in + let ฮณ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ value; M.get_constant (| "ruint::ZERO" |) ] + |) + |) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" + ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::context::inner_evm_context::InnerEvmContext") + [ DB ], + "load_account", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ M.read (| self |) ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "touch", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ M.read (| self |) ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer", + 0 + |) in + let value := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ]; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::journaled_state::JournaledState", + "transfer", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "caller" + |); + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |); + M.read (| value |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::journaled_state::JournaledState", + "checkpoint_revert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ M.read (| self |) ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| checkpoint |) + ] + |) + |) in + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ + return_result; + Value.Tuple [ M.read (| result |) ] + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + "call_precompile", + [] + |), + [ + M.read (| self |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "bytecode_address" + |) + |); + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "input" + |); + M.read (| gas |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.match_operator (| + M.SubPointer.get_struct_record_field (| + result, + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Continue" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Stop" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Return" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Bool false |))) + ] + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_commit", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ M.read (| self |) ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_revert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ M.read (| self |) ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| checkpoint |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameOrResult", + "new_call_result", + [] + |), + [ + M.read (| result |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "return_memory_offset" + |) + ] + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "is_empty", + [] + |), + [ bytecode ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ contract := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::contract::Contract", + "new_with_context", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "input" + |) + ] + |); + M.read (| bytecode |); + Value.StructTuple + "core::option::Option::Some" + [ M.read (| code_hash |) ]; + M.read (| inputs |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameOrResult", + "new_call_frame", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "return_memory_offset" + |) + ] + |); + M.read (| checkpoint |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::Interpreter", + "new", + [] + |), + [ + M.read (| contract |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "limit", + [] + |), + [ gas ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_static" + |) + |) + ] + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_commit", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ M.read (| self |) ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ + return_result; + Value.Tuple + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Stop" + [] + ] + ] + |) + |))) + ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_make_call_frame : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "make_call_frame" (make_call_frame DB). + End Impl_revm_context_evm_context_EvmContext_DB. + End evm_context. +End context. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/inner_evm_context.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/inner_evm_context.md new file mode 100644 index 00000000..30751570 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/context/inner_evm_context.md @@ -0,0 +1,4596 @@ +# ๐Ÿ“ inner_evm_context.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/context/inner_evm_context.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module context. + Module inner_evm_context. + (* StructRecord + { + name := "InnerEvmContext"; + ty_params := [ "DB" ]; + fields := + [ + ("env", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ]); + ("journaled_state", Ty.path "revm::journaled_state::JournaledState"); + ("db", DB); + ("error", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ]) + ]; + } *) + + Module Impl_core_fmt_Debug_where_core_fmt_Debug_DB_where_revm_primitives_db_Database_DB_where_core_fmt_Debug_associated_type_for_revm_context_inner_evm_context_InnerEvmContext_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ]. + + (* Debug *) + Definition fmt (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "InnerEvmContext" |); + M.read (| Value.String "env" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |)); + M.read (| Value.String "journaled_state" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |)); + M.read (| Value.String "db" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |)); + M.read (| Value.String "error" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt DB)) ]. + End Impl_core_fmt_Debug_where_core_fmt_Debug_DB_where_revm_primitives_db_Database_DB_where_core_fmt_Debug_associated_type_for_revm_context_inner_evm_context_InnerEvmContext_DB. + + Module Impl_core_clone_Clone_where_revm_primitives_db_Database_DB_where_core_clone_Clone_DB_where_core_clone_Clone_associated_type_for_revm_context_inner_evm_context_InnerEvmContext_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ]. + + (* + fn clone(&self) -> Self { + Self { + env: self.env.clone(), + journaled_state: self.journaled_state.clone(), + db: self.db.clone(), + error: self.error.clone(), + #[cfg(feature = "optimism")] + l1_block_info: self.l1_block_info.clone(), + } + } + *) + Definition clone (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::context::inner_evm_context::InnerEvmContext" + [ + ("env", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + ] + |)); + ("journaled_state", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::journaled_state::JournaledState", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |)); + ("db", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", DB, [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |)); + ("error", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone DB)) ]. + End Impl_core_clone_Clone_where_revm_primitives_db_Database_DB_where_core_clone_Clone_DB_where_core_clone_Clone_associated_type_for_revm_context_inner_evm_context_InnerEvmContext_DB. + + Module Impl_revm_context_inner_evm_context_InnerEvmContext_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ]. + + (* + pub fn new(db: DB) -> Self { + Self { + env: Box::default(), + journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), + db, + error: Ok(()), + #[cfg(feature = "optimism")] + l1_block_info: None, + } + } + *) + Definition new (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ db ] => + ltac:(M.monadic + (let db := M.alloc (| db |) in + Value.StructRecord + "revm::context::inner_evm_context::InnerEvmContext" + [ + ("env", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm_primitives::env::Env"; Ty.path "alloc::alloc::Global" ], + [], + "default", + [] + |), + [] + |)); + ("journaled_state", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "new", + [] + |), + [ + Value.StructTuple "revm_primitives::specification::SpecId::LATEST" []; + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |) + ] + |)); + ("db", M.read (| db |)); + ("error", Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ]) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "new" (new DB). + + (* + pub fn new_with_env(db: DB, env: Box) -> Self { + Self { + env, + journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), + db, + error: Ok(()), + #[cfg(feature = "optimism")] + l1_block_info: None, + } + } + *) + Definition new_with_env (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ db; env ] => + ltac:(M.monadic + (let db := M.alloc (| db |) in + let env := M.alloc (| env |) in + Value.StructRecord + "revm::context::inner_evm_context::InnerEvmContext" + [ + ("env", M.read (| env |)); + ("journaled_state", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "new", + [] + |), + [ + Value.StructTuple "revm_primitives::specification::SpecId::LATEST" []; + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |) + ] + |)); + ("db", M.read (| db |)); + ("error", Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ]) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_with_env : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "new_with_env" (new_with_env DB). + + (* + pub fn with_db(self, db: ODB) -> InnerEvmContext { + InnerEvmContext { + env: self.env, + journaled_state: self.journaled_state, + db, + error: Ok(()), + #[cfg(feature = "optimism")] + l1_block_info: self.l1_block_info, + } + } + *) + Definition with_db (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ ODB ], [ self; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let db := M.alloc (| db |) in + Value.StructRecord + "revm::context::inner_evm_context::InnerEvmContext" + [ + ("env", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |)); + ("journaled_state", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + |)); + ("db", M.read (| db |)); + ("error", Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ]) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_db : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "with_db" (with_db DB). + + (* + pub const fn spec_id(&self) -> SpecId { + self.journaled_state.spec + } + *) + Definition spec_id (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |), + "revm::journaled_state::JournaledState", + "spec" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_spec_id : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "spec_id" (spec_id DB). + + (* + pub fn load_access_list(&mut self) -> Result<(), EVMError> { + for (address, slots) in self.env.tx.access_list.iter() { + self.journaled_state + .initial_account_load( *address, slots, &mut self.db)?; + } + Ok(()) + } + *) + Definition load_access_list (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ] + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" + ] + ] + ], + "iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "access_list" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ2_1 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let address := M.alloc (| ฮณ2_0 |) in + let slots := M.alloc (| ฮณ2_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ]; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::journaled_state::JournaledState", + "initial_account_load", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| M.read (| address |) |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ M.read (| slots |) ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_access_list : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "load_access_list" (load_access_list DB). + + (* + pub fn env(&mut self) -> &mut Env { + &mut self.env + } + *) + Definition env (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_env : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "env" (env DB). + + (* + pub fn take_error(&mut self) -> Result<(), EVMError> { + core::mem::replace(&mut self.error, Ok(())) + } + *) + Definition take_error (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_function (| + "core::mem::replace", + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |); + Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_take_error : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "take_error" (take_error DB). + + (* + pub fn block_hash(&mut self, number: U256) -> Result> { + self.db.block_hash(number).map_err(EVMError::Database) + } + *) + Definition block_hash (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes"; Ty.associated ], + "map_err", + [ + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "block_hash", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |); + M.read (| number |) + ] + |); + M.constructor_as_closure "revm_primitives::result::EVMError::Database" + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_block_hash : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "block_hash" (block_hash DB). + + (* + pub fn touch(&mut self, address: &Address) { + self.journaled_state.touch(address); + } + *) + Definition touch (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "touch", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_touch : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "touch" (touch DB). + + (* + pub fn load_account( + &mut self, + address: Address, + ) -> Result<(&mut Account, bool), EVMError> { + self.journaled_state.load_account(address, &mut self.db) + } + *) + Definition load_account (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_account : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "load_account" (load_account DB). + + (* + pub fn load_account_exist( + &mut self, + address: Address, + ) -> Result> { + self.journaled_state + .load_account_exist(address, &mut self.db) + } + *) + Definition load_account_exist (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account_exist", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_account_exist : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "load_account_exist" (load_account_exist DB). + + (* + pub fn balance(&mut self, address: Address) -> Result<(U256, bool), EVMError> { + self.journaled_state + .load_account(address, &mut self.db) + .map(|(acc, is_cold)| (acc.info.balance, is_cold)) + } + *) + Definition balance (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map", + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "bool" ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ] + ] + ] + (Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "bool" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let acc := M.copy (| ฮณ0_0 |) in + let is_cold := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |); + M.read (| is_cold |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_balance : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "balance" (balance DB). + + (* + pub fn code(&mut self, address: Address) -> Result<(Bytecode, bool), EVMError> { + self.journaled_state + .load_code(address, &mut self.db) + .map(|(a, is_cold)| (a.info.code.clone().unwrap(), is_cold)) + } + *) + Definition code (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map", + [ + Ty.tuple [ Ty.path "revm_primitives::bytecode::Bytecode"; Ty.path "bool" ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ] + ] + ] + (Ty.tuple [ Ty.path "revm_primitives::bytecode::Bytecode"; Ty.path "bool" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_code", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let a := M.copy (| ฮณ0_0 |) in + let is_cold := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::bytecode::Bytecode" ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::bytecode::Bytecode" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code" + |) + ] + |) + ] + |); + M.read (| is_cold |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_code : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "code" (code DB). + + (* + pub fn code_hash(&mut self, address: Address) -> Result<(B256, bool), EVMError> { + let (acc, is_cold) = self.journaled_state.load_code(address, &mut self.db)?; + if acc.is_empty() { + return Ok((B256::ZERO, is_cold)); + } + Ok((acc.info.code_hash, is_cold)) + } + *) + Definition code_hash (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_code", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let acc := M.copy (| ฮณ0_0 |) in + let is_cold := M.copy (| ฮณ0_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_empty", + [] + |), + [ M.read (| acc |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| + M.get_constant (| + "alloy_primitives::bits::fixed::ZERO" + |) + |); + M.read (| is_cold |) + ] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.Tuple + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code_hash" + |) + |); + M.read (| is_cold |) + ] + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_code_hash : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "code_hash" (code_hash DB). + + (* + pub fn sload( + &mut self, + address: Address, + index: U256, + ) -> Result<(U256, bool), EVMError> { + // account is always warm. reference on that statement https://eips.ethereum.org/EIPS/eip-2929 see `Note 2:` + self.journaled_state.sload(address, index, &mut self.db) + } + *) + Definition sload (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "sload", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.read (| index |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_sload : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "sload" (sload DB). + + (* + pub fn sstore( + &mut self, + address: Address, + index: U256, + value: U256, + ) -> Result> { + self.journaled_state + .sstore(address, index, value, &mut self.db) + } + *) + Definition sstore (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address; index; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + let value := M.alloc (| value |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "sstore", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.read (| index |); + M.read (| value |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_sstore : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "sstore" (sstore DB). + + (* + pub fn tload(&mut self, address: Address, index: U256) -> U256 { + self.journaled_state.tload(address, index) + } + *) + Definition tload (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "tload", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_tload : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "tload" (tload DB). + + (* + pub fn tstore(&mut self, address: Address, index: U256, value: U256) { + self.journaled_state.tstore(address, index, value) + } + *) + Definition tstore (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address; index; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + let value := M.alloc (| value |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "tstore", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.read (| index |); + M.read (| value |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_tstore : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "tstore" (tstore DB). + + (* + pub fn selfdestruct( + &mut self, + address: Address, + target: Address, + ) -> Result> { + self.journaled_state + .selfdestruct(address, target, &mut self.db) + } + *) + Definition selfdestruct (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address; target ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let target := M.alloc (| target |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "selfdestruct", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.read (| target |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_selfdestruct : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "selfdestruct" (selfdestruct DB). + + (* + pub fn make_eofcreate_frame( + &mut self, + spec_id: SpecId, + inputs: &EOFCreateInput, + ) -> Result> { + let return_error = |e| { + Ok(FrameOrResult::new_eofcreate_result( + InterpreterResult { + result: e, + gas: Gas::new(inputs.gas_limit), + output: Bytes::new(), + }, + inputs.created_address, + inputs.return_memory_range.clone(), + )) + }; + + // Check depth + if self.journaled_state.depth() > CALL_STACK_LIMIT { + return return_error(InstructionResult::CallTooDeep); + } + + // Fetch balance of caller. + let (caller_balance, _) = self.balance(inputs.caller)?; + + // Check if caller has enough balance to send to the created contract. + if caller_balance < inputs.value { + return return_error(InstructionResult::OutOfFunds); + } + + // Increase nonce of caller and check if it overflows + if self.journaled_state.inc_nonce(inputs.caller).is_none() { + // can't happen on mainnet. + return return_error(InstructionResult::Return); + } + + // Load account so it needs to be marked as warm for access list. + self.journaled_state + .load_account(inputs.created_address, &mut self.db)?; + + // create account, transfer funds and make the journal checkpoint. + let checkpoint = match self.journaled_state.create_account_checkpoint( + inputs.caller, + inputs.created_address, + inputs.value, + spec_id, + ) { + Ok(checkpoint) => checkpoint, + Err(e) => { + return return_error(e); + } + }; + + let contract = Contract::new( + Bytes::new(), + // fine to clone as it is Bytes. + Bytecode::Eof(inputs.eof_init_code.clone()), + None, + inputs.created_address, + inputs.caller, + inputs.value, + ); + + let mut interpreter = Interpreter::new(contract, inputs.gas_limit, false); + // EOF init will enable RETURNCONTRACT opcode. + interpreter.set_is_eof_init(); + + Ok(FrameOrResult::new_eofcreate_frame( + inputs.created_address, + inputs.return_memory_range.clone(), + checkpoint, + interpreter, + )) + } + *) + Definition make_eofcreate_frame (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; spec_id; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let spec_id := M.alloc (| spec_id |) in + let inputs := M.alloc (| inputs |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ return_error := + M.alloc (| + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameOrResult", + "new_eofcreate_result", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter::InterpreterResult" + [ + ("result", M.read (| e |)); + ("gas", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "gas_limit" + |) + |) + ] + |)); + ("output", + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |)) + ]; + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "created_address" + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "return_memory_range" + |) + ] + |) + ] + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "depth", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |)) + (M.read (| + M.get_constant (| "revm::evm::CALL_STACK_LIMIT" |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ + return_error; + Value.Tuple + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + [] + ] + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "bool" ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::inner_evm_context::InnerEvmContext") + [ DB ], + "balance", + [] + |), + [ + M.read (| self |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "caller" + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let caller_balance := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "lt", + [] + |), + [ + caller_balance; + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "value" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ + return_error; + Value.Tuple + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + [] + ] + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "u64" ], + "is_none", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "inc_nonce", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "caller" + |) + |) + ] + |) + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ + return_error; + Value.Tuple + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Return" + [] + ] + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "created_address" + |) + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ checkpoint := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "create_account_checkpoint", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "caller" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "created_address" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "value" + |) + |); + M.read (| spec_id |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let checkpoint := M.copy (| ฮณ0_0 |) in + checkpoint)); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ return_error; Value.Tuple [ M.read (| e |) ] ] + |) + |) + |) + |) + |))) + ] + |) + |) in + let~ contract := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::contract::Contract", + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |); + Value.StructTuple + "revm_primitives::bytecode::Bytecode::Eof" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::eof::Eof", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "eof_init_code" + |) + ] + |) + ]; + Value.StructTuple "core::option::Option::None" []; + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "created_address" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "caller" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "value" + |) + |) + ] + |) + |) in + let~ interpreter := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "new", + [] + |), + [ + M.read (| contract |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "gas_limit" + |) + |); + Value.Bool false + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "set_is_eof_init", + [] + |), + [ interpreter ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameOrResult", + "new_eofcreate_frame", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "created_address" + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::ops::range::Range") + [ Ty.path "usize" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput", + "return_memory_range" + |) + ] + |); + M.read (| checkpoint |); + M.read (| interpreter |) + ] + |) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_make_eofcreate_frame : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "make_eofcreate_frame" (make_eofcreate_frame DB). + + (* + pub fn eofcreate_return( + &mut self, + interpreter_result: &mut InterpreterResult, + address: Address, + journal_checkpoint: JournalCheckpoint, + ) { + // Note we still execute RETURN opcode and return the bytes. + // In EOF those opcodes should abort execution. + // + // In RETURN gas is still protecting us from ddos and in oog, + // behaviour will be same as if it failed on return. + // + // Bytes of RETURN will drained in `insert_eofcreate_outcome`. + if interpreter_result.result != InstructionResult::ReturnContract { + self.journaled_state.checkpoint_revert(journal_checkpoint); + return; + } + + // commit changes reduces depth by -1. + self.journaled_state.checkpoint_commit(); + + // decode bytecode has a performance hit, but it has reasonable restrains. + let bytecode = + Eof::decode(interpreter_result.output.clone()).expect("Eof is already verified"); + + // eof bytecode is going to be hashed. + self.journaled_state + .set_code(address, Bytecode::Eof(bytecode)); + } + *) + Definition eofcreate_return (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ SPEC ], [ self; interpreter_result; address; journal_checkpoint ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interpreter_result := M.alloc (| interpreter_result |) in + let address := M.alloc (| address |) in + let journal_checkpoint := M.alloc (| journal_checkpoint |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "revm_interpreter::instruction_result::InstructionResult", + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ], + "ne", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |); + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_revert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| journal_checkpoint |) + ] + |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_commit", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |) + |) in + let~ bytecode := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::eof::Eof"; + Ty.path "revm_primitives::bytecode::eof::EofDecodeError" + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::eof::Eof", + "decode", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |) + ] + |); + M.read (| Value.String "Eof is already verified" |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "set_code", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + Value.StructTuple + "revm_primitives::bytecode::Bytecode::Eof" + [ M.read (| bytecode |) ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_eofcreate_return : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "eofcreate_return" (eofcreate_return DB). + + (* + pub fn make_create_frame( + &mut self, + spec_id: SpecId, + inputs: &CreateInputs, + ) -> Result> { + // Prepare crate. + let gas = Gas::new(inputs.gas_limit); + + let return_error = |e| { + Ok(FrameOrResult::new_create_result( + InterpreterResult { + result: e, + gas, + output: Bytes::new(), + }, + None, + )) + }; + + // Check depth + if self.journaled_state.depth() > CALL_STACK_LIMIT { + return return_error(InstructionResult::CallTooDeep); + } + + // Fetch balance of caller. + let (caller_balance, _) = self.balance(inputs.caller)?; + + // Check if caller has enough balance to send to the created contract. + if caller_balance < inputs.value { + return return_error(InstructionResult::OutOfFunds); + } + + // Increase nonce of caller and check if it overflows + let old_nonce; + if let Some(nonce) = self.journaled_state.inc_nonce(inputs.caller) { + old_nonce = nonce - 1; + } else { + return return_error(InstructionResult::Return); + } + + // Create address + let mut init_code_hash = B256::ZERO; + let created_address = match inputs.scheme { + CreateScheme::Create => inputs.caller.create(old_nonce), + CreateScheme::Create2 { salt } => { + init_code_hash = keccak256(&inputs.init_code); + inputs.caller.create2(salt.to_be_bytes(), init_code_hash) + } + }; + + // Load account so it needs to be marked as warm for access list. + self.journaled_state + .load_account(created_address, &mut self.db)?; + + // create account, transfer funds and make the journal checkpoint. + let checkpoint = match self.journaled_state.create_account_checkpoint( + inputs.caller, + created_address, + inputs.value, + spec_id, + ) { + Ok(checkpoint) => checkpoint, + Err(e) => { + return return_error(e); + } + }; + + let bytecode = Bytecode::new_raw(inputs.init_code.clone()); + + let contract = Contract::new( + Bytes::new(), + bytecode, + Some(init_code_hash), + created_address, + inputs.caller, + inputs.value, + ); + + Ok(FrameOrResult::new_create_frame( + created_address, + checkpoint, + Interpreter::new(contract, gas.limit(), false), + )) + } + *) + Definition make_create_frame (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; spec_id; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let spec_id := M.alloc (| spec_id |) in + let inputs := M.alloc (| inputs |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ gas := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "gas_limit" + |) + |) + ] + |) + |) in + let~ return_error := + M.alloc (| + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameOrResult", + "new_create_result", + [] + |), + [ + Value.StructRecord + "revm_interpreter::interpreter::InterpreterResult" + [ + ("result", M.read (| e |)); + ("gas", M.read (| gas |)); + ("output", + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |)) + ]; + Value.StructTuple "core::option::Option::None" [] + ] + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "depth", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |)) + (M.read (| + M.get_constant (| "revm::evm::CALL_STACK_LIMIT" |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ + return_error; + Value.Tuple + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + [] + ] + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "bool" ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::inner_evm_context::InnerEvmContext") + [ DB ], + "balance", + [] + |), + [ + M.read (| self |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let caller_balance := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "lt", + [] + |), + [ + caller_balance; + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "value" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ + return_error; + Value.Tuple + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + [] + ] + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ old_nonce := M.copy (| Value.DeclaredButUndefined |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "inc_nonce", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |) + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let nonce := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + old_nonce, + BinOp.Wrap.sub + Integer.U64 + (M.read (| nonce |)) + (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ + return_error; + Value.Tuple + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Return" + [] + ] + ] + |) + |) + |) + |) + |))) + ] + |) in + let~ init_code_hash := + M.copy (| + M.get_constant (| "alloy_primitives::bits::fixed::ZERO" |) + |) in + let~ created_address := + M.copy (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "scheme" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::env::CreateScheme::Create" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "create", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |); + M.read (| old_nonce |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::env::CreateScheme::Create2", + "salt" + |) in + let salt := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + init_code_hash, + M.call_closure (| + M.get_function (| + "alloy_primitives::utils::keccak256", + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "init_code" + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "create2", + [ + Ty.apply (Ty.path "array") [ Ty.path "u8" ]; + Ty.path "alloy_primitives::bits::fixed::FixedBytes" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "to_be_bytes", + [] + |), + [ salt ] + |); + M.read (| init_code_hash |) + ] + |) + |))) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| created_address |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ checkpoint := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "create_account_checkpoint", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |) + |); + M.read (| created_address |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "value" + |) + |); + M.read (| spec_id |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let checkpoint := M.copy (| ฮณ0_0 |) in + checkpoint)); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Err", + 0 + |) in + let e := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ]), + [ + Ty.tuple + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ] + ], + "call", + [] + |), + [ return_error; Value.Tuple [ M.read (| e |) ] ] + |) + |) + |) + |) + |))) + ] + |) + |) in + let~ bytecode := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "new_raw", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "init_code" + |) + ] + |) + ] + |) + |) in + let~ contract := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::contract::Contract", + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |); + M.read (| bytecode |); + Value.StructTuple + "core::option::Option::Some" + [ M.read (| init_code_hash |) ]; + M.read (| created_address |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "value" + |) + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameOrResult", + "new_create_frame", + [] + |), + [ + M.read (| created_address |); + M.read (| checkpoint |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "new", + [] + |), + [ + M.read (| contract |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "limit", + [] + |), + [ gas ] + |); + Value.Bool false + ] + |) + ] + |) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_make_create_frame : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "make_create_frame" (make_create_frame DB). + + (* + pub fn call_return( + &mut self, + interpreter_result: &InterpreterResult, + journal_checkpoint: JournalCheckpoint, + ) { + // revert changes or not. + if matches!(interpreter_result.result, return_ok!()) { + self.journaled_state.checkpoint_commit(); + } else { + self.journaled_state.checkpoint_revert(journal_checkpoint); + } + } + *) + Definition call_return (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; interpreter_result; journal_checkpoint ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interpreter_result := M.alloc (| interpreter_result |) in + let journal_checkpoint := M.alloc (| journal_checkpoint |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Continue" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Stop" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Return" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_commit", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_revert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| journal_checkpoint |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_call_return : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "call_return" (call_return DB). + + (* + pub fn create_return( + &mut self, + interpreter_result: &mut InterpreterResult, + address: Address, + journal_checkpoint: JournalCheckpoint, + ) { + // if return is not ok revert and return. + if !matches!(interpreter_result.result, return_ok!()) { + self.journaled_state.checkpoint_revert(journal_checkpoint); + return; + } + // Host error if present on execution + // if ok, check contract creation limit and calculate gas deduction on output len. + // + // EIP-3541: Reject new contract code starting with the 0xEF byte + if SPEC::enabled(LONDON) + && !interpreter_result.output.is_empty() + && interpreter_result.output.first() == Some(&0xEF) + { + self.journaled_state.checkpoint_revert(journal_checkpoint); + interpreter_result.result = InstructionResult::CreateContractStartingWithEF; + return; + } + + // EIP-170: Contract code size limit + // By default limit is 0x6000 (~25kb) + if SPEC::enabled(SPURIOUS_DRAGON) + && interpreter_result.output.len() + > self + .env + .cfg + .limit_contract_code_size + .unwrap_or(MAX_CODE_SIZE) + { + self.journaled_state.checkpoint_revert(journal_checkpoint); + interpreter_result.result = InstructionResult::CreateContractSizeLimit; + return; + } + let gas_for_code = interpreter_result.output.len() as u64 * gas::CODEDEPOSIT; + if !interpreter_result.gas.record_cost(gas_for_code) { + // record code deposit gas cost and check if we are out of gas. + // EIP-2 point 3: If contract creation does not have enough gas to pay for the + // final gas fee for adding the contract code to the state, the contract + // creation fails (i.e. goes out-of-gas) rather than leaving an empty contract. + if SPEC::enabled(HOMESTEAD) { + self.journaled_state.checkpoint_revert(journal_checkpoint); + interpreter_result.result = InstructionResult::OutOfGas; + return; + } else { + interpreter_result.output = Bytes::new(); + } + } + // if we have enough gas we can commit changes. + self.journaled_state.checkpoint_commit(); + + // Do analysis of bytecode straight away. + let bytecode = match self.env.cfg.perf_analyse_created_bytecodes { + AnalysisKind::Raw => Bytecode::new_raw(interpreter_result.output.clone()), + AnalysisKind::Analyse => { + to_analysed(Bytecode::new_raw(interpreter_result.output.clone())) + } + }; + + // set code + self.journaled_state.set_code(address, bytecode); + + interpreter_result.result = InstructionResult::Return; + } + *) + Definition create_return (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ SPEC ], [ self; interpreter_result; address; journal_checkpoint ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interpreter_result := M.alloc (| interpreter_result |) in + let address := M.alloc (| address |) in + let journal_checkpoint := M.alloc (| journal_checkpoint |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.read (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Continue" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Stop" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Return" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_revert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| journal_checkpoint |) + ] + |) + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::LONDON" + [] + ] + |), + ltac:(M.monadic + (UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "is_empty", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |) + ] + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "u8" ] ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "u8" ] ] + ], + "eq", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "u8" ], + "first", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |) + ] + |) + ] + |) + |); + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ M.alloc (| Value.Integer 239 |) ] + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_revert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| journal_checkpoint |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CreateContractStartingWithEF" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + [] + ] + |), + ltac:(M.monadic + (BinOp.Pure.gt + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |) + ] + |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "usize" ], + "unwrap_or", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "cfg" + |), + "revm_primitives::env::CfgEnv", + "limit_contract_code_size" + |) + |); + M.read (| + M.get_constant (| + "revm_primitives::constants::MAX_CODE_SIZE" + |) + |) + ] + |)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_revert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| journal_checkpoint |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CreateContractSizeLimit" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ gas_for_code := + M.alloc (| + BinOp.Wrap.mul + Integer.U64 + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |) + ] + |))) + (M.read (| + M.get_constant (| "revm_interpreter::gas::constants::CODEDEPOSIT" |) + |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_cost", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |); + M.read (| gas_for_code |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::HOMESTEAD" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_revert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| journal_checkpoint |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::OutOfGas" + [] + |) in + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bytes_::Bytes", + "new", + [] + |), + [] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_commit", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |) + |) in + let~ bytecode := + M.copy (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "cfg" + |), + "revm_primitives::env::CfgEnv", + "perf_analyse_created_bytecodes" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::env::AnalysisKind::Raw" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "new_raw", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::env::AnalysisKind::Analyse" + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::interpreter::analysis::to_analysed", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "new_raw", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |) + ] + |) + ] + |) + |))) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "set_code", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.read (| bytecode |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter_result |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |), + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Return" + [] + |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_create_return : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "create_return" (create_return DB). + End Impl_revm_context_inner_evm_context_InnerEvmContext_DB. + End inner_evm_context. +End context. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/emptydb.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/emptydb.md new file mode 100644 index 00000000..0777eb40 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/emptydb.md @@ -0,0 +1,513 @@ +# ๐Ÿ“ emptydb.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/emptydb.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module emptydb. + Axiom EmptyDB : + (Ty.path "revm::db::emptydb::EmptyDB") = + (Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ]). + + (* StructRecord + { + name := "EmptyDBTyped"; + ty_params := [ "E" ]; + fields := [ ("_phantom", Ty.apply (Ty.path "core::marker::PhantomData") [ E ]) ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_emptydb_EmptyDBTyped_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ]. + + (* + fn clone(&self) -> Self { + *self + } + *) + Definition clone (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (E : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self E) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone E)) ]. + End Impl_core_clone_Clone_for_revm_db_emptydb_EmptyDBTyped_E. + + Module Impl_core_marker_Copy_for_revm_db_emptydb_EmptyDBTyped_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ]. + + Axiom Implements : + forall (E : Ty.t), + M.IsTraitInstance + "core::marker::Copy" + (Self E) + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_db_emptydb_EmptyDBTyped_E. + + Module Impl_core_default_Default_for_revm_db_emptydb_EmptyDBTyped_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ]. + + (* + fn default() -> Self { + Self::new() + } + *) + Definition default (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ], + "new", + [] + |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (E : Ty.t), + M.IsTraitInstance + "core::default::Default" + (Self E) + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method (default E)) ]. + End Impl_core_default_Default_for_revm_db_emptydb_EmptyDBTyped_E. + + Module Impl_core_fmt_Debug_for_revm_db_emptydb_EmptyDBTyped_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ]. + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EmptyDB").finish_non_exhaustive() + } + *) + Definition fmt (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "finish_non_exhaustive", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct", + [] + |), + [ M.read (| f |); M.read (| Value.String "EmptyDB" |) ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (E : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self E) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt E)) ]. + End Impl_core_fmt_Debug_for_revm_db_emptydb_EmptyDBTyped_E. + + Module Impl_core_cmp_PartialEq_for_revm_db_emptydb_EmptyDBTyped_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ]. + + (* + fn eq(&self, _: &Self) -> bool { + true + } + *) + Definition eq (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; ฮฒ1 ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let ฮฒ1 := M.alloc (| ฮฒ1 |) in + M.match_operator (| ฮฒ1, [ fun ฮณ => ltac:(M.monadic (Value.Bool true)) ] |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (E : Ty.t), + M.IsTraitInstance + "core::cmp::PartialEq" + (Self E) + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method (eq E)) ]. + End Impl_core_cmp_PartialEq_for_revm_db_emptydb_EmptyDBTyped_E. + + Module Impl_core_cmp_Eq_for_revm_db_emptydb_EmptyDBTyped_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ]. + + Axiom Implements : + forall (E : Ty.t), + M.IsTraitInstance + "core::cmp::Eq" + (Self E) + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_cmp_Eq_for_revm_db_emptydb_EmptyDBTyped_E. + + Module Impl_revm_db_emptydb_EmptyDBTyped_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ]. + + (* + pub fn new() -> Self { + Self { + _phantom: PhantomData, + } + } + *) + Definition new (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::emptydb::EmptyDBTyped" + [ ("_phantom", Value.StructTuple "core::marker::PhantomData" []) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (E : Ty.t), + M.IsAssociatedFunction (Self E) "new" (new E). + + (* + pub fn new_keccak_block_hash() -> Self { + Self::new() + } + *) + Definition new_keccak_block_hash (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ], + "new", + [] + |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_keccak_block_hash : + forall (E : Ty.t), + M.IsAssociatedFunction (Self E) "new_keccak_block_hash" (new_keccak_block_hash E). + End Impl_revm_db_emptydb_EmptyDBTyped_E. + + Module Impl_revm_primitives_db_Database_for_revm_db_emptydb_EmptyDBTyped_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ]. + + (* type Error = E; *) + Definition _Error (E : Ty.t) : Ty.t := E. + + (* + fn basic(&mut self, address: Address) -> Result, Self::Error> { + ::basic_ref(self, address) + } + *) + Definition basic (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ], + [], + "basic_ref", + [] + |), + [ M.read (| self |); M.read (| address |) ] + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash(&mut self, code_hash: B256) -> Result { + ::code_by_hash_ref(self, code_hash) + } + *) + Definition code_by_hash (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ], + [], + "code_by_hash_ref", + [] + |), + [ M.read (| self |); M.read (| code_hash |) ] + |))) + | _, _ => M.impossible + end. + + (* + fn storage(&mut self, address: Address, index: U256) -> Result { + ::storage_ref(self, address, index) + } + *) + Definition storage (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ], + [], + "storage_ref", + [] + |), + [ M.read (| self |); M.read (| address |); M.read (| index |) ] + |))) + | _, _ => M.impossible + end. + + (* + fn block_hash(&mut self, number: U256) -> Result { + ::block_hash_ref(self, number) + } + *) + Definition block_hash (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ], + [], + "block_hash_ref", + [] + |), + [ M.read (| self |); M.read (| number |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (E : Ty.t), + M.IsTraitInstance + "revm_primitives::db::Database" + (Self E) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error E)); + ("basic", InstanceField.Method (basic E)); + ("code_by_hash", InstanceField.Method (code_by_hash E)); + ("storage", InstanceField.Method (storage E)); + ("block_hash", InstanceField.Method (block_hash E)) + ]. + End Impl_revm_primitives_db_Database_for_revm_db_emptydb_EmptyDBTyped_E. + + Module Impl_revm_primitives_db_DatabaseRef_for_revm_db_emptydb_EmptyDBTyped_E. + Definition Self (E : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::emptydb::EmptyDBTyped") [ E ]. + + (* type Error = E; *) + Definition _Error (E : Ty.t) : Ty.t := E. + + (* + fn basic_ref(&self, _address: Address) -> Result, Self::Error> { + Ok(None) + } + *) + Definition basic_ref (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; _address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + Value.StructTuple + "core::result::Result::Ok" + [ Value.StructTuple "core::option::Option::None" [] ])) + | _, _ => M.impossible + end. + + (* + fn code_by_hash_ref(&self, _code_hash: B256) -> Result { + Ok(Bytecode::default()) + } + *) + Definition code_by_hash_ref (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; _code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _code_hash := M.alloc (| _code_hash |) in + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + (* + fn storage_ref(&self, _address: Address, _index: U256) -> Result { + Ok(U256::default()) + } + *) + Definition storage_ref (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; _address; _index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + let _index := M.alloc (| _index |) in + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "ruint::Uint", + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + (* + fn block_hash_ref(&self, number: U256) -> Result { + Ok(keccak256(number.to_string().as_bytes())) + } + *) + Definition block_hash_ref (E : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self E in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_function (| + "alloy_primitives::utils::keccak256", + [ Ty.apply (Ty.path "&") [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ] ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "alloc::string::String", + "as_bytes", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "alloc::string::ToString", + Ty.path "ruint::Uint", + [], + "to_string", + [] + |), + [ number ] + |) + |) + ] + |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (E : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseRef" + (Self E) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error E)); + ("basic_ref", InstanceField.Method (basic_ref E)); + ("code_by_hash_ref", InstanceField.Method (code_by_hash_ref E)); + ("storage_ref", InstanceField.Method (storage_ref E)); + ("block_hash_ref", InstanceField.Method (block_hash_ref E)) + ]. + End Impl_revm_primitives_db_DatabaseRef_for_revm_db_emptydb_EmptyDBTyped_E. + End emptydb. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/in_memory_db.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/in_memory_db.md new file mode 100644 index 00000000..58833f0d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/in_memory_db.md @@ -0,0 +1,5267 @@ +# ๐Ÿ“ in_memory_db.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/in_memory_db.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module in_memory_db. + Axiom InMemoryDB : + (Ty.path "revm::db::in_memory_db::InMemoryDB") = + (Ty.apply + (Ty.path "revm::db::in_memory_db::CacheDB") + [ + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ]). + + (* StructRecord + { + name := "CacheDB"; + ty_params := [ "ExtDB" ]; + fields := + [ + ("accounts", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ]); + ("contracts", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ]); + ("logs", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ]); + ("block_hashes", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "std::hash::random::RandomState" + ]); + ("db", ExtDB) + ]; + } *) + + Module Impl_core_fmt_Debug_where_core_fmt_Debug_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + Definition Self (ExtDB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ]. + + (* Debug *) + Definition fmt (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field5_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CacheDB" |); + M.read (| Value.String "accounts" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |)); + M.read (| Value.String "contracts" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "contracts" + |)); + M.read (| Value.String "logs" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "logs" + |)); + M.read (| Value.String "block_hashes" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "block_hashes" + |)); + M.read (| Value.String "db" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (ExtDB : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self ExtDB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt ExtDB)) ]. + End Impl_core_fmt_Debug_where_core_fmt_Debug_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + + Module Impl_core_clone_Clone_where_core_clone_Clone_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + Definition Self (ExtDB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ]. + + (* Clone *) + Definition clone (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::in_memory_db::CacheDB" + [ + ("accounts", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |) + ] + |)); + ("contracts", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "contracts" + |) + ] + |)); + ("logs", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "logs" + |) + ] + |)); + ("block_hashes", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "block_hashes" + |) + ] + |)); + ("db", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", ExtDB, [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (ExtDB : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self ExtDB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone ExtDB)) ]. + End Impl_core_clone_Clone_where_core_clone_Clone_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + + Module Impl_core_default_Default_where_core_default_Default_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + Definition Self (ExtDB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ]. + + (* + fn default() -> Self { + Self::new(ExtDB::default()) + } + *) + Definition default (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ], + "new", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| "core::default::Default", ExtDB, [], "default", [] |), + [] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (ExtDB : Ty.t), + M.IsTraitInstance + "core::default::Default" + (Self ExtDB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method (default ExtDB)) ]. + End Impl_core_default_Default_where_core_default_Default_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + + Module Impl_revm_db_in_memory_db_CacheDB_ExtDB. + Definition Self (ExtDB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ]. + + (* + pub fn new(db: ExtDB) -> Self { + let mut contracts = HashMap::new(); + contracts.insert(KECCAK_EMPTY, Bytecode::default()); + contracts.insert(B256::ZERO, Bytecode::default()); + Self { + accounts: HashMap::new(), + contracts, + logs: Vec::default(), + block_hashes: HashMap::new(), + db, + } + } + *) + Definition new (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ db ] => + ltac:(M.monadic + (let db := M.alloc (| db |) in + M.read (| + let~ contracts := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + contracts; + M.read (| M.get_constant (| "revm_primitives::utilities::KECCAK_EMPTY" |) |); + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "default", + [] + |), + [] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + contracts; + M.read (| M.get_constant (| "alloy_primitives::bits::fixed::ZERO" |) |); + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "default", + [] + |), + [] + |) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::db::in_memory_db::CacheDB" + [ + ("accounts", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("contracts", M.read (| contracts |)); + ("logs", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)); + ("block_hashes", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("db", M.read (| db |)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (ExtDB : Ty.t), + M.IsAssociatedFunction (Self ExtDB) "new" (new ExtDB). + + (* + pub fn insert_contract(&mut self, account: &mut AccountInfo) { + if let Some(code) = &account.code { + if !code.is_empty() { + if account.code_hash == KECCAK_EMPTY { + account.code_hash = code.hash_slow(); + } + self.contracts + .entry(account.code_hash) + .or_insert_with(|| code.clone()); + } + } + if account.code_hash == B256::ZERO { + account.code_hash = KECCAK_EMPTY; + } + } + *) + Definition insert_contract (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; account ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let account := M.alloc (| account |) in + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::AccountInfo", + "code" + |) + |) in + let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let code := M.alloc (| ฮณ1_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "is_empty", + [] + |), + [ M.read (| code |) ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "alloy_primitives::bits::fixed::FixedBytes", + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::AccountInfo", + "code_hash" + |); + M.get_constant (| + "revm_primitives::utilities::KECCAK_EMPTY" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::AccountInfo", + "code_hash" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "hash_slow", + [] + |), + [ M.read (| code |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::Entry") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ], + "or_insert_with", + [ + Ty.function + [ Ty.tuple [] ] + (Ty.path "revm_primitives::bytecode::Bytecode") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "contracts" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::AccountInfo", + "code_hash" + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ M.read (| code |) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::AccountInfo", + "code_hash" + |); + M.get_constant (| "alloy_primitives::bits::fixed::ZERO" |) + ] + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::AccountInfo", + "code_hash" + |), + M.read (| + M.get_constant (| "revm_primitives::utilities::KECCAK_EMPTY" |) + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_contract : + forall (ExtDB : Ty.t), + M.IsAssociatedFunction (Self ExtDB) "insert_contract" (insert_contract ExtDB). + + (* + pub fn insert_account_info(&mut self, address: Address, mut info: AccountInfo) { + self.insert_contract(&mut info); + self.accounts.entry(address).or_default().info = info; + } + *) + Definition insert_account_info (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; address; info ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let info := M.alloc (| info |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ], + "insert_contract", + [] + |), + [ M.read (| self |); info ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::Entry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount" + ], + "or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |); + M.read (| address |) + ] + |) + ] + |), + "revm::db::in_memory_db::DbAccount", + "info" + |), + M.read (| info |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_account_info : + forall (ExtDB : Ty.t), + M.IsAssociatedFunction (Self ExtDB) "insert_account_info" (insert_account_info ExtDB). + (* + pub fn load_account(&mut self, address: Address) -> Result<&mut DbAccount, ExtDB::Error> { + let db = &self.db; + match self.accounts.entry(address) { + Entry::Occupied(entry) => Ok(entry.into_mut()), + Entry::Vacant(entry) => Ok(entry.insert( + db.basic_ref(address)? + .map(|info| DbAccount { + info, + ..Default::default() + }) + .unwrap_or_else(DbAccount::new_not_existing), + )), + } + } + *) + Definition load_account (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ db := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount" + ], + "into_mut", + [] + |), + [ M.read (| entry |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::in_memory_db::DbAccount" ], + "unwrap_or_else", + [ + Ty.function + [] + (Ty.path "revm::db::in_memory_db::DbAccount") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "map", + [ + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.function + [ + Ty.tuple + [ Ty.path "revm_primitives::state::AccountInfo" + ] + ] + (Ty.path "revm::db::in_memory_db::DbAccount") + ] + |), + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ]; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "basic_ref", + [] + |), + [ M.read (| db |); M.read (| address |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::in_memory_db::DbAccount" + ]; + Ty.associated + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + M.struct_record_update + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path + "revm::db::in_memory_db::DbAccount", + [], + "default", + [] + |), + [] + |)) + [ ("info", M.read (| info |)) ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + M.get_associated_function (| + Ty.path "revm::db::in_memory_db::DbAccount", + "new_not_existing", + [] + |) + ] + |) + ] + |) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_account : + forall (ExtDB : Ty.t), + M.IsAssociatedFunction (Self ExtDB) "load_account" (load_account ExtDB). + + (* + pub fn insert_account_storage( + &mut self, + address: Address, + slot: U256, + value: U256, + ) -> Result<(), ExtDB::Error> { + let account = self.load_account(address)?; + account.storage.insert(slot, value); + Ok(()) + } + *) + Definition insert_account_storage (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; address; slot; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let slot := M.alloc (| slot |) in + let value := M.alloc (| value |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ account := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm::db::in_memory_db::DbAccount" ]; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ], + "load_account", + [] + |), + [ M.read (| self |); M.read (| address |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.associated ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "core::convert::Infallible"; Ty.associated ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm::db::in_memory_db::DbAccount", + "storage" + |); + M.read (| slot |); + M.read (| value |) + ] + |) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_account_storage : + forall (ExtDB : Ty.t), + M.IsAssociatedFunction (Self ExtDB) "insert_account_storage" (insert_account_storage ExtDB). + + (* + pub fn replace_account_storage( + &mut self, + address: Address, + storage: HashMap, + ) -> Result<(), ExtDB::Error> { + let account = self.load_account(address)?; + account.account_state = AccountState::StorageCleared; + account.storage = storage.into_iter().collect(); + Ok(()) + } + *) + Definition replace_account_storage (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; address; storage ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let storage := M.alloc (| storage |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ account := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm::db::in_memory_db::DbAccount" ]; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ], + "load_account", + [] + |), + [ M.read (| self |); M.read (| address |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.associated ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "core::convert::Infallible"; Ty.associated ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm::db::in_memory_db::DbAccount", + "account_state" + |), + Value.StructTuple "revm::db::in_memory_db::AccountState::StorageCleared" [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm::db::in_memory_db::DbAccount", + "storage" + |), + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ M.read (| storage |) ] + |) + ] + |) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_replace_account_storage : + forall (ExtDB : Ty.t), + M.IsAssociatedFunction + (Self ExtDB) + "replace_account_storage" + (replace_account_storage ExtDB). + End Impl_revm_db_in_memory_db_CacheDB_ExtDB. + + + Module Impl_revm_primitives_db_DatabaseCommit_for_revm_db_in_memory_db_CacheDB_ExtDB. + Definition Self (ExtDB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ]. + + (* + fn commit(&mut self, changes: HashMap) { + for (address, mut account) in changes { + if !account.is_touched() { + continue; + } + if account.is_selfdestructed() { + let db_account = self.accounts.entry(address).or_default(); + db_account.storage.clear(); + db_account.account_state = AccountState::NotExisting; + db_account.info = AccountInfo::default(); + continue; + } + let is_newly_created = account.is_created(); + self.insert_contract(&mut account.info); + + let db_account = self.accounts.entry(address).or_default(); + db_account.info = account.info; + + db_account.account_state = if is_newly_created { + db_account.storage.clear(); + AccountState::StorageCleared + } else if db_account.account_state.is_storage_cleared() { + // Preserve old account state if it already exists + AccountState::StorageCleared + } else { + AccountState::Touched + }; + db_account.storage.extend( + account + .storage + .into_iter() + .map(|(key, value)| (key, value.present_value())), + ); + } + } + *) + Definition commit (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; changes ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let changes := M.alloc (| changes |) in + M.read (| + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ M.read (| changes |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let address := M.copy (| ฮณ1_0 |) in + let account := M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::Account", + "is_touched", + [] + |), + [ account ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| M.read (| M.continue (||) |) |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_selfdestructed", + [] + |), + [ account ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ db_account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::Entry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::in_memory_db::DbAccount" + ], + "or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::in_memory_db::DbAccount"; + Ty.path + "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |); + M.read (| address |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path + "std::hash::random::RandomState" + ], + "clear", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| db_account |), + "revm::db::in_memory_db::DbAccount", + "storage" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| db_account |), + "revm::db::in_memory_db::DbAccount", + "account_state" + |), + Value.StructTuple + "revm::db::in_memory_db::AccountState::NotExisting" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| db_account |), + "revm::db::in_memory_db::DbAccount", + "info" + |), + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path + "revm_primitives::state::AccountInfo", + [], + "default", + [] + |), + [] + |) + |) in + M.continue (||) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ is_newly_created := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_created", + [] + |), + [ account ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::db::in_memory_db::CacheDB") + [ ExtDB ], + "insert_contract", + [] + |), + [ + M.read (| self |); + M.SubPointer.get_struct_record_field (| + account, + "revm_primitives::state::Account", + "info" + |) + ] + |) + |) in + let~ db_account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::Entry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount" + ], + "or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |); + M.read (| address |) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| db_account |), + "revm::db::in_memory_db::DbAccount", + "info" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm_primitives::state::Account", + "info" + |) + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| db_account |), + "revm::db::in_memory_db::DbAccount", + "account_state" + |), + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use is_newly_created in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path + "std::hash::random::RandomState" + ], + "clear", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| db_account |), + "revm::db::in_memory_db::DbAccount", + "storage" + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "revm::db::in_memory_db::AccountState::StorageCleared" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::in_memory_db::AccountState", + "is_storage_cleared", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| db_account |), + "revm::db::in_memory_db::DbAccount", + "account_state" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "revm::db::in_memory_db::AccountState::StorageCleared" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm::db::in_memory_db::AccountState::Touched" + [] + |))) + ] + |))) + ] + |) + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::Extend", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.tuple + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ] + ], + "extend", + [ + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]) + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| db_account |), + "revm::db::in_memory_db::DbAccount", + "storage" + |); + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "map", + [ + Ty.tuple + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm_primitives::state::Account", + "storage" + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let key := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| key |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::StorageSlot", + "present_value", + [] + |), + [ value ] + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (ExtDB : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseCommit" + (Self ExtDB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("commit", InstanceField.Method (commit ExtDB)) ]. + End Impl_revm_primitives_db_DatabaseCommit_for_revm_db_in_memory_db_CacheDB_ExtDB. + + Module Impl_revm_primitives_db_Database_where_revm_primitives_db_DatabaseRef_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + Definition Self (ExtDB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ]. + + (* type Error = ExtDB::Error; *) + Definition _Error (ExtDB : Ty.t) : Ty.t := Ty.associated. + + (* + fn basic(&mut self, address: Address) -> Result, Self::Error> { + let basic = match self.accounts.entry(address) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert( + self.db + .basic_ref(address)? + .map(|info| DbAccount { + info, + ..Default::default() + }) + .unwrap_or_else(DbAccount::new_not_existing), + ), + }; + Ok(basic.info()) + } + *) + Definition basic (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ basic := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount" + ], + "into_mut", + [] + |), + [ M.read (| entry |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::in_memory_db::DbAccount" ], + "unwrap_or_else", + [ + Ty.function + [] + (Ty.path "revm::db::in_memory_db::DbAccount") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "map", + [ + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.function + [ + Ty.tuple + [ Ty.path "revm_primitives::state::AccountInfo" + ] + ] + (Ty.path "revm::db::in_memory_db::DbAccount") + ] + |), + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ]; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "basic_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| address |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ]; + Ty.associated + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + M.struct_record_update + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path + "revm::db::in_memory_db::DbAccount", + [], + "default", + [] + |), + [] + |)) + [ ("info", M.read (| info |)) ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + M.get_associated_function (| + Ty.path "revm::db::in_memory_db::DbAccount", + "new_not_existing", + [] + |) + ] + |) + ] + |) + |))) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::in_memory_db::DbAccount", + "info", + [] + |), + [ M.read (| basic |) ] + |) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash(&mut self, code_hash: B256) -> Result { + match self.contracts.entry(code_hash) { + Entry::Occupied(entry) => Ok(entry.get().clone()), + Entry::Vacant(entry) => { + // if you return code bytes when basic fn is called this function is not needed. + Ok(entry.insert(self.db.code_by_hash_ref(code_hash)?).clone()) + } + } + } + *) + Definition code_by_hash (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "contracts" + |); + M.read (| code_hash |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ], + "get", + [] + |), + [ entry ] + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "code_by_hash_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| code_hash |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_primitives::bytecode::Bytecode"; + Ty.associated + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |) + ] + |) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + (* + fn storage(&mut self, address: Address, index: U256) -> Result { + match self.accounts.entry(address) { + Entry::Occupied(mut acc_entry) => { + let acc_entry = acc_entry.get_mut(); + match acc_entry.storage.entry(index) { + Entry::Occupied(entry) => Ok( *entry.get()), + Entry::Vacant(entry) => { + if matches!( + acc_entry.account_state, + AccountState::StorageCleared | AccountState::NotExisting + ) { + Ok(U256::ZERO) + } else { + let slot = self.db.storage_ref(address, index)?; + entry.insert(slot); + Ok(slot) + } + } + } + } + Entry::Vacant(acc_entry) => { + // acc needs to be loaded for us to access slots. + let info = self.db.basic_ref(address)?; + let (account, value) = if info.is_some() { + let value = self.db.storage_ref(address, index)?; + let mut account: DbAccount = info.into(); + account.storage.insert(index, value); + (account, value) + } else { + (info.into(), U256::ZERO) + }; + acc_entry.insert(account); + Ok(value) + } + } + } + *) + Definition storage (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let acc_entry := M.copy (| ฮณ0_0 |) in + let~ acc_entry := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount" + ], + "get_mut", + [] + |), + [ acc_entry ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| acc_entry |), + "revm::db::in_memory_db::DbAccount", + "storage" + |); + M.read (| index |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ], + "get", + [] + |), + [ entry ] + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| acc_entry |), + "revm::db::in_memory_db::DbAccount", + "account_state" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::StorageCleared" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::NotExisting" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Bool false |))) + ] + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ M.read (| M.get_constant (| "ruint::ZERO" |) |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ slot := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "ruint::Uint"; Ty.associated ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "storage_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| address |); + M.read (| index |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "ruint::Uint"; + Ty.associated + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" + ], + "insert", + [] + |), + [ M.read (| entry |); M.read (| slot |) ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ M.read (| slot |) ] + |))) + ] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let acc_entry := M.copy (| ฮณ0_0 |) in + let~ info := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "basic_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| address |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "ruint::Uint"; Ty.associated ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "is_some", + [] + |), + [ info ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ value := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "ruint::Uint"; Ty.associated ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "storage_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| address |); + M.read (| index |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "ruint::Uint"; Ty.associated + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ account := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [ Ty.path "revm::db::in_memory_db::DbAccount" ], + "into", + [] + |), + [ M.read (| info |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + account, + "revm::db::in_memory_db::DbAccount", + "storage" + |); + M.read (| index |); + M.read (| value |) + ] + |) + |) in + M.alloc (| + Value.Tuple [ M.read (| account |); M.read (| value |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [ Ty.path "revm::db::in_memory_db::DbAccount" ], + "into", + [] + |), + [ M.read (| info |) ] + |); + M.read (| M.get_constant (| "ruint::ZERO" |) |) + ] + |))) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let account := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount" + ], + "insert", + [] + |), + [ M.read (| acc_entry |); M.read (| account |) ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ M.read (| value |) ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + (* + fn block_hash(&mut self, number: U256) -> Result { + match self.block_hashes.entry(number) { + Entry::Occupied(entry) => Ok( *entry.get()), + Entry::Vacant(entry) => { + let hash = self.db.block_hash_ref(number)?; + entry.insert(hash); + Ok(hash) + } + } + } + *) + Definition block_hash (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "block_hashes" + |); + M.read (| number |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "ruint::Uint"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes" + ], + "get", + [] + |), + [ entry ] + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ hash := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "block_hash_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| number |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.associated + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "ruint::Uint"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes" + ], + "insert", + [] + |), + [ M.read (| entry |); M.read (| hash |) ] + |) + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ M.read (| hash |) ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (ExtDB : Ty.t), + M.IsTraitInstance + "revm_primitives::db::Database" + (Self ExtDB) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error ExtDB)); + ("basic", InstanceField.Method (basic ExtDB)); + ("code_by_hash", InstanceField.Method (code_by_hash ExtDB)); + ("storage", InstanceField.Method (storage ExtDB)); + ("block_hash", InstanceField.Method (block_hash ExtDB)) + ]. + End Impl_revm_primitives_db_Database_where_revm_primitives_db_DatabaseRef_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + + Module Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + Definition Self (ExtDB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::in_memory_db::CacheDB") [ ExtDB ]. + + (* type Error = ExtDB::Error; *) + Definition _Error (ExtDB : Ty.t) : Ty.t := Ty.associated. + + (* + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + match self.accounts.get(&address) { + Some(acc) => Ok(acc.info()), + None => self.db.basic_ref(address), + } + } + *) + Definition basic_ref (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |); + address + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let acc := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::in_memory_db::DbAccount", + "info", + [] + |), + [ M.read (| acc |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "basic_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| address |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + match self.contracts.get(&code_hash) { + Some(entry) => Ok(entry.clone()), + None => self.db.code_by_hash_ref(code_hash), + } + } + *) + Definition code_by_hash_ref (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "contracts" + |); + code_hash + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ M.read (| entry |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "code_by_hash_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| code_hash |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + (* + fn storage_ref(&self, address: Address, index: U256) -> Result { + match self.accounts.get(&address) { + Some(acc_entry) => match acc_entry.storage.get(&index) { + Some(entry) => Ok( *entry), + None => { + if matches!( + acc_entry.account_state, + AccountState::StorageCleared | AccountState::NotExisting + ) { + Ok(U256::ZERO) + } else { + self.db.storage_ref(address, index) + } + } + }, + None => self.db.storage_ref(address, index), + } + } + *) + Definition storage_ref (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "accounts" + |); + address + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let acc_entry := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "ruint::Uint" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| acc_entry |), + "revm::db::in_memory_db::DbAccount", + "storage" + |); + index + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ M.read (| M.read (| entry |) |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| acc_entry |), + "revm::db::in_memory_db::DbAccount", + "account_state" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::StorageCleared" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::NotExisting" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ M.read (| M.get_constant (| "ruint::ZERO" |) |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "storage_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| address |); + M.read (| index |) + ] + |) + |))) + ] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "storage_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| address |); + M.read (| index |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + (* + fn block_hash_ref(&self, number: U256) -> Result { + match self.block_hashes.get(&number) { + Some(entry) => Ok( *entry), + None => self.db.block_hash_ref(number), + } + } + *) + Definition block_hash_ref (ExtDB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self ExtDB in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "ruint::Uint" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "block_hashes" + |); + number + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ M.read (| M.read (| entry |) |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseRef", + ExtDB, + [], + "block_hash_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::CacheDB", + "db" + |); + M.read (| number |) + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (ExtDB : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseRef" + (Self ExtDB) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error ExtDB)); + ("basic_ref", InstanceField.Method (basic_ref ExtDB)); + ("code_by_hash_ref", InstanceField.Method (code_by_hash_ref ExtDB)); + ("storage_ref", InstanceField.Method (storage_ref ExtDB)); + ("block_hash_ref", InstanceField.Method (block_hash_ref ExtDB)) + ]. + End Impl_revm_primitives_db_DatabaseRef_where_revm_primitives_db_DatabaseRef_ExtDB_for_revm_db_in_memory_db_CacheDB_ExtDB. + + (* StructRecord + { + name := "DbAccount"; + ty_params := []; + fields := + [ + ("info", Ty.path "revm_primitives::state::AccountInfo"); + ("account_state", Ty.path "revm::db::in_memory_db::AccountState"); + ("storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ]) + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_db_in_memory_db_DbAccount. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::DbAccount". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "DbAccount" |); + M.read (| Value.String "info" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::DbAccount", + "info" + |)); + M.read (| Value.String "account_state" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::DbAccount", + "account_state" + |)); + M.read (| Value.String "storage" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::DbAccount", + "storage" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_in_memory_db_DbAccount. + + Module Impl_core_clone_Clone_for_revm_db_in_memory_db_DbAccount. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::DbAccount". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::in_memory_db::DbAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountInfo", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::DbAccount", + "info" + |) + ] + |)); + ("account_state", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::db::in_memory_db::AccountState", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::DbAccount", + "account_state" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::DbAccount", + "storage" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_in_memory_db_DbAccount. + + Module Impl_core_default_Default_for_revm_db_in_memory_db_DbAccount. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::DbAccount". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::in_memory_db::DbAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::AccountInfo", + [], + "default", + [] + |), + [] + |)); + ("account_state", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::in_memory_db::AccountState", + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_in_memory_db_DbAccount. + + Module Impl_revm_db_in_memory_db_DbAccount. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::DbAccount". + + (* + pub fn new_not_existing() -> Self { + Self { + account_state: AccountState::NotExisting, + ..Default::default() + } + } + *) + Definition new_not_existing (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.struct_record_update + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::in_memory_db::DbAccount", + [], + "default", + [] + |), + [] + |)) + [ + ("account_state", + Value.StructTuple "revm::db::in_memory_db::AccountState::NotExisting" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_not_existing : + M.IsAssociatedFunction Self "new_not_existing" new_not_existing. + + (* + pub fn info(&self) -> Option { + if matches!(self.account_state, AccountState::NotExisting) { + None + } else { + Some(self.info.clone()) + } + } + *) + Definition info (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::DbAccount", + "account_state" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::NotExisting" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountInfo", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::in_memory_db::DbAccount", + "info" + |) + ] + |) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_info : M.IsAssociatedFunction Self "info" info. + End Impl_revm_db_in_memory_db_DbAccount. + + Module Impl_core_convert_From_core_option_Option_revm_primitives_state_AccountInfo_for_revm_db_in_memory_db_DbAccount. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::DbAccount". + + (* + fn from(from: Option) -> Self { + from.map(Self::from).unwrap_or_else(Self::new_not_existing) + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ from ] => + ltac:(M.monadic + (let from := M.alloc (| from |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::in_memory_db::DbAccount" ], + "unwrap_or_else", + [ Ty.function [] (Ty.path "revm::db::in_memory_db::DbAccount") ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "map", + [ + Ty.path "revm::db::in_memory_db::DbAccount"; + Ty.function + [ Ty.path "revm_primitives::state::AccountInfo" ] + (Ty.path "revm::db::in_memory_db::DbAccount") + ] + |), + [ + M.read (| from |); + M.get_trait_method (| + "core::convert::From", + Ty.path "revm::db::in_memory_db::DbAccount", + [ Ty.path "revm_primitives::state::AccountInfo" ], + "from", + [] + |) + ] + |); + M.get_associated_function (| + Ty.path "revm::db::in_memory_db::DbAccount", + "new_not_existing", + [] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ + (* T *) + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_core_option_Option_revm_primitives_state_AccountInfo_for_revm_db_in_memory_db_DbAccount. + + Module Impl_core_convert_From_revm_primitives_state_AccountInfo_for_revm_db_in_memory_db_DbAccount. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::DbAccount". + + (* + fn from(info: AccountInfo) -> Self { + Self { + info, + account_state: AccountState::None, + ..Default::default() + } + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ info ] => + ltac:(M.monadic + (let info := M.alloc (| info |) in + M.struct_record_update + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::in_memory_db::DbAccount", + [], + "default", + [] + |), + [] + |)) + [ + ("info", M.read (| info |)); + ("account_state", Value.StructTuple "revm::db::in_memory_db::AccountState::None" []) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) [ (* T *) Ty.path "revm_primitives::state::AccountInfo" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_primitives_state_AccountInfo_for_revm_db_in_memory_db_DbAccount. + + (* + Enum AccountState + { + ty_params := []; + variants := + [ + { + name := "NotExisting"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Touched"; + item := StructTuple []; + discriminant := None; + }; + { + name := "StorageCleared"; + item := StructTuple []; + discriminant := None; + }; + { + name := "None"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_db_in_memory_db_AccountState. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::AccountState". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::NotExisting" + |) in + M.alloc (| M.read (| Value.String "NotExisting" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::Touched" + |) in + M.alloc (| M.read (| Value.String "Touched" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::StorageCleared" + |) in + M.alloc (| M.read (| Value.String "StorageCleared" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::None" + |) in + M.alloc (| M.read (| Value.String "None" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_in_memory_db_AccountState. + + Module Impl_core_clone_Clone_for_revm_db_in_memory_db_AccountState. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::AccountState". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::NotExisting" + |) in + M.alloc (| + Value.StructTuple "revm::db::in_memory_db::AccountState::NotExisting" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::Touched" + |) in + M.alloc (| + Value.StructTuple "revm::db::in_memory_db::AccountState::Touched" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::StorageCleared" + |) in + M.alloc (| + Value.StructTuple "revm::db::in_memory_db::AccountState::StorageCleared" [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| ฮณ, "revm::db::in_memory_db::AccountState::None" |) in + M.alloc (| + Value.StructTuple "revm::db::in_memory_db::AccountState::None" [] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_in_memory_db_AccountState. + + Module Impl_core_default_Default_for_revm_db_in_memory_db_AccountState. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::AccountState". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic (Value.StructTuple "revm::db::in_memory_db::AccountState::None" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_in_memory_db_AccountState. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_in_memory_db_AccountState. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::AccountState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_in_memory_db_AccountState. + + Module Impl_core_cmp_PartialEq_for_revm_db_in_memory_db_AccountState. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::AccountState". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::in_memory_db::AccountState" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::in_memory_db::AccountState" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_in_memory_db_AccountState. + + Module Impl_core_marker_StructuralEq_for_revm_db_in_memory_db_AccountState. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::AccountState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_in_memory_db_AccountState. + + Module Impl_core_cmp_Eq_for_revm_db_in_memory_db_AccountState. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::AccountState". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_in_memory_db_AccountState. + + Module Impl_core_hash_Hash_for_revm_db_in_memory_db_AccountState. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::AccountState". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::in_memory_db::AccountState" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_db_in_memory_db_AccountState. + + Module Impl_revm_db_in_memory_db_AccountState. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::AccountState". + + (* + pub fn is_storage_cleared(&self) -> bool { + matches!(self, AccountState::StorageCleared) + } + *) + Definition is_storage_cleared (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::in_memory_db::AccountState::StorageCleared" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_storage_cleared : + M.IsAssociatedFunction Self "is_storage_cleared" is_storage_cleared. + End Impl_revm_db_in_memory_db_AccountState. + + (* StructTuple + { + name := "BenchmarkDB"; + ty_params := []; + fields := + [ + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes" + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_db_in_memory_db_BenchmarkDB. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::BenchmarkDB". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "BenchmarkDB" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::in_memory_db::BenchmarkDB", + 0 + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::in_memory_db::BenchmarkDB", + 1 + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_in_memory_db_BenchmarkDB. + + Module Impl_core_default_Default_for_revm_db_in_memory_db_BenchmarkDB. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::BenchmarkDB". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm::db::in_memory_db::BenchmarkDB" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "default", + [] + |), + [] + |); + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_in_memory_db_BenchmarkDB. + + Module Impl_core_clone_Clone_for_revm_db_in_memory_db_BenchmarkDB. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::BenchmarkDB". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructTuple + "revm::db::in_memory_db::BenchmarkDB" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::in_memory_db::BenchmarkDB", + 0 + |) + ] + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::in_memory_db::BenchmarkDB", + 1 + |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_in_memory_db_BenchmarkDB. + + Module Impl_revm_db_in_memory_db_BenchmarkDB. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::BenchmarkDB". + + (* + pub fn new_bytecode(bytecode: Bytecode) -> Self { + let hash = bytecode.hash_slow(); + Self(bytecode, hash) + } + *) + Definition new_bytecode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ bytecode ] => + ltac:(M.monadic + (let bytecode := M.alloc (| bytecode |) in + M.read (| + let~ hash := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "hash_slow", + [] + |), + [ bytecode ] + |) + |) in + M.alloc (| + Value.StructTuple + "revm::db::in_memory_db::BenchmarkDB" + [ M.read (| bytecode |); M.read (| hash |) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_bytecode : + M.IsAssociatedFunction Self "new_bytecode" new_bytecode. + End Impl_revm_db_in_memory_db_BenchmarkDB. + + Module Impl_revm_primitives_db_Database_for_revm_db_in_memory_db_BenchmarkDB. + Definition Self : Ty.t := Ty.path "revm::db::in_memory_db::BenchmarkDB". + + (* type Error = Infallible; *) + Definition _Error : Ty.t := Ty.path "core::convert::Infallible". + + (* + fn basic(&mut self, address: Address) -> Result, Self::Error> { + if address == Address::ZERO { + return Ok(Some(AccountInfo { + nonce: 1, + balance: U256::from(10000000), + code: Some(self.0.clone()), + code_hash: self.1, + })); + } + if address == Address::with_last_byte(1) { + return Ok(Some(AccountInfo { + nonce: 0, + balance: U256::from(10000000), + code: None, + code_hash: KECCAK_EMPTY, + })); + } + Ok(None) + } + *) + Definition basic (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + address; + M.get_constant (| "alloy_primitives::bits::address::ZERO" |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm_primitives::state::AccountInfo" + [ + ("nonce", Value.Integer 1); + ("balance", + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 10000000 ] + |)); + ("code", + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::in_memory_db::BenchmarkDB", + 0 + |) + ] + |) + ]); + ("code_hash", + M.read (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::in_memory_db::BenchmarkDB", + 1 + |) + |)) + ] + ] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + address; + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::bits::address::Address", + "with_last_byte", + [] + |), + [ Value.Integer 1 ] + |) + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm_primitives::state::AccountInfo" + [ + ("nonce", Value.Integer 0); + ("balance", + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "i32" ] + |), + [ Value.Integer 10000000 ] + |)); + ("code", + Value.StructTuple + "core::option::Option::None" + []); + ("code_hash", + M.read (| + M.get_constant (| + "revm_primitives::utilities::KECCAK_EMPTY" + |) + |)) + ] + ] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ Value.StructTuple "core::option::Option::None" [] ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash(&mut self, _code_hash: B256) -> Result { + Ok(Bytecode::default()) + } + *) + Definition code_by_hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _code_hash := M.alloc (| _code_hash |) in + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + (* + fn storage(&mut self, _address: Address, _index: U256) -> Result { + Ok(U256::default()) + } + *) + Definition storage (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _address; _index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _address := M.alloc (| _address |) in + let _index := M.alloc (| _index |) in + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "ruint::Uint", + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + (* + fn block_hash(&mut self, _number: U256) -> Result { + Ok(B256::default()) + } + *) + Definition block_hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; _number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _number := M.alloc (| _number |) in + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "revm_primitives::db::Database" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty _Error); + ("basic", InstanceField.Method basic); + ("code_by_hash", InstanceField.Method code_by_hash); + ("storage", InstanceField.Method storage); + ("block_hash", InstanceField.Method block_hash) + ]. + End Impl_revm_primitives_db_Database_for_revm_db_in_memory_db_BenchmarkDB. + End in_memory_db. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/account_status.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/account_status.md new file mode 100644 index 00000000..57f7dcc5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/account_status.md @@ -0,0 +1,1669 @@ +# ๐Ÿ“ account_status.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/account_status.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module account_status. + (* + Enum AccountStatus + { + ty_params := []; + variants := + [ + { + name := "LoadedNotExisting"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Loaded"; + item := StructTuple []; + discriminant := None; + }; + { + name := "LoadedEmptyEIP161"; + item := StructTuple []; + discriminant := None; + }; + { + name := "InMemoryChange"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Changed"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Destroyed"; + item := StructTuple []; + discriminant := None; + }; + { + name := "DestroyedChanged"; + item := StructTuple []; + discriminant := None; + }; + { + name := "DestroyedAgain"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_account_status_AccountStatus. + + Module Impl_core_marker_Copy_for_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_db_states_account_status_AccountStatus. + + Module Impl_core_default_Default_for_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_account_status_AccountStatus. + + Module Impl_core_fmt_Debug_for_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + M.alloc (| M.read (| Value.String "LoadedNotExisting" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + M.alloc (| M.read (| Value.String "Loaded" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + M.alloc (| M.read (| Value.String "LoadedEmptyEIP161" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + M.alloc (| M.read (| Value.String "InMemoryChange" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + M.alloc (| M.read (| Value.String "Changed" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + M.alloc (| M.read (| Value.String "Destroyed" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + M.alloc (| M.read (| Value.String "DestroyedChanged" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + M.alloc (| M.read (| Value.String "DestroyedAgain" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_account_status_AccountStatus. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_account_status_AccountStatus. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::account_status::AccountStatus" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::account_status::AccountStatus" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_account_status_AccountStatus. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_account_status_AccountStatus. + + Module Impl_core_cmp_Eq_for_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_account_status_AccountStatus. + + Module Impl_core_hash_Hash_for_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::account_status::AccountStatus" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "isize", + [], + "hash", + [ __H ] + |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_db_states_account_status_AccountStatus. + + Module Impl_revm_db_states_account_status_AccountStatus. + Definition Self : Ty.t := Ty.path "revm::db::states::account_status::AccountStatus". + + (* + pub fn is_not_modified(&self) -> bool { + matches!( + self, + AccountStatus::LoadedNotExisting + | AccountStatus::Loaded + | AccountStatus::LoadedEmptyEIP161 + ) + } + *) + Definition is_not_modified (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_not_modified : + M.IsAssociatedFunction Self "is_not_modified" is_not_modified. + + (* + pub fn was_destroyed(&self) -> bool { + matches!( + self, + AccountStatus::Destroyed + | AccountStatus::DestroyedChanged + | AccountStatus::DestroyedAgain + ) + } + *) + Definition was_destroyed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_was_destroyed : + M.IsAssociatedFunction Self "was_destroyed" was_destroyed. + + (* + pub fn is_storage_known(&self) -> bool { + matches!( + self, + AccountStatus::LoadedNotExisting + | AccountStatus::InMemoryChange + | AccountStatus::Destroyed + | AccountStatus::DestroyedChanged + | AccountStatus::DestroyedAgain + ) + } + *) + Definition is_storage_known (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_storage_known : + M.IsAssociatedFunction Self "is_storage_known" is_storage_known. + + (* + pub fn is_modified_and_not_destroyed(&self) -> bool { + matches!(self, AccountStatus::Changed | AccountStatus::InMemoryChange) + } + *) + Definition is_modified_and_not_destroyed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_modified_and_not_destroyed : + M.IsAssociatedFunction Self "is_modified_and_not_destroyed" is_modified_and_not_destroyed. + + (* + pub fn on_created(&self) -> AccountStatus { + match self { + // if account was destroyed previously just copy new info to it. + AccountStatus::DestroyedAgain + | AccountStatus::Destroyed + | AccountStatus::DestroyedChanged => AccountStatus::DestroyedChanged, + // if account is loaded from db. + AccountStatus::LoadedNotExisting + // Loaded empty eip161 to creates is not possible as CREATE2 was added after EIP-161 + | AccountStatus::LoadedEmptyEIP161 + | AccountStatus::Loaded + | AccountStatus::Changed + | AccountStatus::InMemoryChange => { + // If account is loaded and not empty this means that account has some balance. + // This means that account cannot be created. + // We are assuming that EVM did necessary checks before allowing account to be created. + AccountStatus::InMemoryChange + } + } + } + *) + Definition on_created (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + [] + |) + | _ => M.impossible (||) + end)) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_on_created : M.IsAssociatedFunction Self "on_created" on_created. + + (* + pub fn on_touched_empty_post_eip161(&self) -> AccountStatus { + match self { + // Account can be touched but not existing. The status should remain the same. + AccountStatus::LoadedNotExisting => AccountStatus::LoadedNotExisting, + // Account can be created empty and only then touched. + AccountStatus::InMemoryChange + | AccountStatus::Destroyed + | AccountStatus::LoadedEmptyEIP161 => AccountStatus::Destroyed, + // Transition to destroy the account. + AccountStatus::DestroyedAgain | AccountStatus::DestroyedChanged => { + AccountStatus::DestroyedAgain + } + // Account statuses considered unreachable. + AccountStatus::Loaded | AccountStatus::Changed => { + unreachable!("Wrong state transition, touch empty is not possible from {self:?}"); + } + } + } + *) + Definition on_touched_empty_post_eip161 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Destroyed" + [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: Wrong state transition, touch empty is not possible from " + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm::db::states::account_status::AccountStatus" + ] + ] + |), + [ self ] + |) + ] + |)) + ] + |) + ] + |) + |) + |) + | _ => M.impossible (||) + end)) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_on_touched_empty_post_eip161 : + M.IsAssociatedFunction Self "on_touched_empty_post_eip161" on_touched_empty_post_eip161. + + (* + pub fn on_touched_created_pre_eip161(&self, had_no_info: bool) -> Option { + match self { + AccountStatus::LoadedEmptyEIP161 => None, + AccountStatus::DestroyedChanged => { + if had_no_info { + None + } else { + Some(AccountStatus::DestroyedChanged) + } + } + AccountStatus::Destroyed | AccountStatus::DestroyedAgain => { + Some(AccountStatus::DestroyedChanged) + } + AccountStatus::InMemoryChange | AccountStatus::LoadedNotExisting => { + Some(AccountStatus::InMemoryChange) + } + AccountStatus::Loaded | AccountStatus::Changed => { + unreachable!("Wrong state transition, touch crate is not possible from {self:?}") + } + } + } + *) + Definition on_touched_created_pre_eip161 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; had_no_info ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let had_no_info := M.alloc (| had_no_info |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use had_no_info in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + [] + ] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + [] + ] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + [] + ] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: Wrong state transition, touch crate is not possible from " + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm::db::states::account_status::AccountStatus" + ] + ] + |), + [ self ] + |) + ] + |)) + ] + |) + ] + |) + |) + |) + | _ => M.impossible (||) + end)) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_on_touched_created_pre_eip161 : + M.IsAssociatedFunction Self "on_touched_created_pre_eip161" on_touched_created_pre_eip161. + + (* + pub fn on_changed(&self, had_no_nonce_and_code: bool) -> AccountStatus { + match self { + // If the account was loaded as not existing, promote it to changed. + // This account was likely created by a balance transfer. + AccountStatus::LoadedNotExisting => AccountStatus::InMemoryChange, + // Change on empty account, should transfer storage if there is any. + // There is possibility that there are storage entries inside db. + // That storage is used in merkle tree calculation before state clear EIP. + AccountStatus::LoadedEmptyEIP161 => AccountStatus::InMemoryChange, + // The account was loaded as existing. + AccountStatus::Loaded => { + if had_no_nonce_and_code { + // account is fully in memory + AccountStatus::InMemoryChange + } else { + // can be contract and some of storage slots can be present inside db. + AccountStatus::Changed + } + } + + // On change, the "changed" type account statuses are preserved. + // Any checks for empty accounts are done outside of this fn. + AccountStatus::Changed => AccountStatus::Changed, + AccountStatus::InMemoryChange => AccountStatus::InMemoryChange, + AccountStatus::DestroyedChanged => AccountStatus::DestroyedChanged, + + // If account is destroyed and then changed this means this is + // balance transfer. + AccountStatus::Destroyed | AccountStatus::DestroyedAgain => { + AccountStatus::DestroyedChanged + } + } + } + *) + Definition on_changed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; had_no_nonce_and_code ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let had_no_nonce_and_code := M.alloc (| had_no_nonce_and_code |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use had_no_nonce_and_code in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Changed" + [] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Changed" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + [] + |) + | _ => M.impossible (||) + end)) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_on_changed : M.IsAssociatedFunction Self "on_changed" on_changed. + + (* + pub fn on_selfdestructed(&self) -> AccountStatus { + match self { + // Non existing account can't be destroyed. + AccountStatus::LoadedNotExisting => AccountStatus::LoadedNotExisting, + // If account is created and selfdestructed in the same block, mark it as destroyed again. + // Note: there is no big difference between Destroyed and DestroyedAgain in this case, + // but was added for clarity. + AccountStatus::DestroyedChanged + | AccountStatus::DestroyedAgain + | AccountStatus::Destroyed => AccountStatus::DestroyedAgain, + + // Transition to destroyed status. + _ => AccountStatus::Destroyed, + } + } + *) + Definition on_selfdestructed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Destroyed" + [] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_on_selfdestructed : + M.IsAssociatedFunction Self "on_selfdestructed" on_selfdestructed. + + (* + pub fn transition(&mut self, other: Self) { + *self = match (self.was_destroyed(), other.was_destroyed()) { + (true, false) => Self::DestroyedChanged, + (false, false) if *self == Self::InMemoryChange => Self::InMemoryChange, + _ => other, + }; + } + *) + Definition transition (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ _ := + M.write (| + M.read (| self |), + M.read (| + M.match_operator (| + M.alloc (| + Value.Tuple + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "was_destroyed", + [] + |), + [ M.read (| self |) ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "was_destroyed", + [] + |), + [ other ] + |) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ0_0 |), + Value.Bool true + |) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ0_1 |), + Value.Bool false + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ0_0 |), + Value.Bool false + |) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ0_1 |), + Value.Bool false + |) in + let ฮณ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::account_status::AccountStatus", + [ Ty.path "revm::db::states::account_status::AccountStatus" ], + "eq", + [] + |), + [ + M.read (| self |); + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + [] + |) + ] + |) + |) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + [] + |))); + fun ฮณ => ltac:(M.monadic other) + ] + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transition : M.IsAssociatedFunction Self "transition" transition. + End Impl_revm_db_states_account_status_AccountStatus. + End account_status. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/bundle_account.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/bundle_account.md new file mode 100644 index 00000000..8fac3f0b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/bundle_account.md @@ -0,0 +1,4500 @@ +# ๐Ÿ“ bundle_account.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/bundle_account.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module bundle_account. + (* StructRecord + { + name := "BundleAccount"; + ty_params := []; + fields := + [ + ("info", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]); + ("original_info", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]); + ("storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ]); + ("status", Ty.path "revm::db::states::account_status::AccountStatus") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_bundle_account_BundleAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_account::BundleAccount". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::bundle_account::BundleAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |) + ] + |)); + ("original_info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "original_info" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |)); + ("status", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::db::states::account_status::AccountStatus", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_bundle_account_BundleAccount. + + Module Impl_core_fmt_Debug_for_revm_db_states_bundle_account_BundleAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_account::BundleAccount". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "BundleAccount" |); + M.read (| Value.String "info" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |)); + M.read (| Value.String "original_info" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "original_info" + |)); + M.read (| Value.String "storage" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |)); + M.read (| Value.String "status" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_bundle_account_BundleAccount. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_bundle_account_BundleAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_account::BundleAccount". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_bundle_account_BundleAccount. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_bundle_account_BundleAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_account::BundleAccount". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "original_info" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::bundle_account::BundleAccount", + "original_info" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::account_status::AccountStatus", + [ Ty.path "revm::db::states::account_status::AccountStatus" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_bundle_account_BundleAccount. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_bundle_account_BundleAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_account::BundleAccount". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_bundle_account_BundleAccount. + + Module Impl_core_cmp_Eq_for_revm_db_states_bundle_account_BundleAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_account::BundleAccount". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_bundle_account_BundleAccount. + + Module Impl_revm_db_states_bundle_account_BundleAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_account::BundleAccount". + + (* + pub fn new( + original_info: Option, + present_info: Option, + storage: StorageWithOriginalValues, + status: AccountStatus, + ) -> Self { + Self { + info: present_info, + original_info, + storage, + status, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ original_info; present_info; storage; status ] => + ltac:(M.monadic + (let original_info := M.alloc (| original_info |) in + let present_info := M.alloc (| present_info |) in + let storage := M.alloc (| storage |) in + let status := M.alloc (| status |) in + Value.StructRecord + "revm::db::states::bundle_account::BundleAccount" + [ + ("info", M.read (| present_info |)); + ("original_info", M.read (| original_info |)); + ("storage", M.read (| storage |)); + ("status", M.read (| status |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn size_hint(&self) -> usize { + 1 + self.storage.len() + } + *) + Definition size_hint (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.add + Integer.Usize + (Value.Integer 1) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_size_hint : M.IsAssociatedFunction Self "size_hint" size_hint. + + (* + pub fn storage_slot(&self, slot: U256) -> Option { + let slot = self.storage.get(&slot).map(|s| s.present_value); + if slot.is_some() { + slot + } else if self.status.is_storage_known() { + Some(U256::ZERO) + } else { + None + } + } + *) + Definition storage_slot (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; slot ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let slot := M.alloc (| slot |) in + M.read (| + let~ slot := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::state::StorageSlot" ] + ], + "map", + [ + Ty.path "ruint::Uint"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + (Ty.path "ruint::Uint") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "ruint::Uint" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |); + slot + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let s := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| s |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + "is_some", + [] + |), + [ slot ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + slot)); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "is_storage_known", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ M.read (| M.get_constant (| "ruint::ZERO" |) |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_storage_slot : + M.IsAssociatedFunction Self "storage_slot" storage_slot. + + (* + pub fn account_info(&self) -> Option { + self.info.clone() + } + *) + Definition account_info (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_account_info : + M.IsAssociatedFunction Self "account_info" account_info. + + (* + pub fn was_destroyed(&self) -> bool { + self.status.was_destroyed() + } + *) + Definition was_destroyed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "was_destroyed", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_was_destroyed : + M.IsAssociatedFunction Self "was_destroyed" was_destroyed. + + (* + pub fn is_info_changed(&self) -> bool { + self.info != self.original_info + } + *) + Definition is_info_changed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "ne", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "original_info" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_info_changed : + M.IsAssociatedFunction Self "is_info_changed" is_info_changed. + + (* + pub fn is_contract_changed(&self) -> bool { + self.info.as_ref().map(|a| a.code_hash) != self.original_info.as_ref().map(|a| a.code_hash) + } + *) + Definition is_contract_changed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ] + ], + "ne", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "map", + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + ] + (Ty.path "alloy_primitives::bits::fixed::FixedBytes") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm_primitives::state::AccountInfo", + "code_hash" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |); + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "map", + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + ] + (Ty.path "alloy_primitives::bits::fixed::FixedBytes") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "original_info" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm_primitives::state::AccountInfo", + "code_hash" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_contract_changed : + M.IsAssociatedFunction Self "is_contract_changed" is_contract_changed. + + (* + pub fn revert(&mut self, revert: AccountRevert) -> bool { + self.status = revert.previous_status; + + match revert.account { + AccountInfoRevert::DoNothing => (), + AccountInfoRevert::DeleteIt => { + self.info = None; + if self.original_info.is_none() { + self.storage = HashMap::new(); + return true; + } else { + // set all storage to zero but preserve original values. + self.storage.iter_mut().for_each(|(_, v)| { + v.present_value = U256::ZERO; + }); + return false; + } + } + AccountInfoRevert::RevertTo(info) => self.info = Some(info), + }; + // revert storage + for (key, slot) in revert.storage { + match slot { + RevertToSlot::Some(value) => { + // Don't overwrite original values if present + // if storage is not present set original value as current value. + self.storage + .entry(key) + .or_insert(StorageSlot::new(value)) + .present_value = value; + } + RevertToSlot::Destroyed => { + // if it was destroyed this means that storage was created and we need to remove it. + self.storage.remove(&key); + } + } + } + false + } + *) + Definition revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; revert ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let revert := M.alloc (| revert |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + revert, + "revm::db::states::reverts::AccountRevert", + "previous_status" + |) + |) + |) in + let~ _ := + M.match_operator (| + M.SubPointer.get_struct_record_field (| + revert, + "revm::db::states::reverts::AccountRevert", + "account" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::DoNothing" + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |), + Value.StructTuple "core::option::Option::None" [] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "is_none", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "original_info" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |) + |) in + M.return_ (| Value.Bool true |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::IterMut") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "for_each", + [ + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "iter_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let v := M.copy (| ฮณ0_1 |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| v |), + "revm_primitives::state::StorageSlot", + "present_value" + |), + M.read (| + M.get_constant (| + "ruint::ZERO" + |) + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + M.return_ (| Value.Bool false |) + |) + |) + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::RevertTo", + 0 + |) in + let info := M.copy (| ฮณ0_0 |) in + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |), + Value.StructTuple "core::option::Option::Some" [ M.read (| info |) ] + |))) + ] + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + revert, + "revm::db::states::reverts::AccountRevert", + "storage" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let key := M.copy (| ฮณ1_0 |) in + let slot := M.copy (| ฮณ1_1 |) in + M.match_operator (| + slot, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::db::states::reverts::RevertToSlot::Some", + 0 + |) in + let value := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::Entry") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + "or_insert", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |); + M.read (| key |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::StorageSlot", + "new", + [] + |), + [ M.read (| value |) ] + |) + ] + |), + "revm_primitives::state::StorageSlot", + "present_value" + |), + M.read (| value |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::RevertToSlot::Destroyed" + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "remove", + [ Ty.path "ruint::Uint" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |); + key + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.alloc (| Value.Bool false |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_revert : M.IsAssociatedFunction Self "revert" revert. + + (* + pub fn update_and_create_revert( + &mut self, + transition: TransitionAccount, + ) -> Option { + let updated_info = transition.info; + let updated_storage = transition.storage; + let updated_status = transition.status; + + // the helper that extends this storage but preserves original value. + let extend_storage = + |this_storage: &mut StorageWithOriginalValues, + storage_update: StorageWithOriginalValues| { + for (key, value) in storage_update { + this_storage.entry(key).or_insert(value).present_value = value.present_value; + } + }; + + let previous_storage_from_update = + |updated_storage: &StorageWithOriginalValues| -> HashMap { + updated_storage + .iter() + .filter(|s| s.1.is_changed()) + .map(|(key, value)| { + ( *key, RevertToSlot::Some(value.previous_or_original_value)) + }) + .collect() + }; + + // Needed for some reverts. + let info_revert = if self.info != updated_info { + AccountInfoRevert::RevertTo(self.info.clone().unwrap_or_default()) + } else { + AccountInfoRevert::DoNothing + }; + + let account_revert = match updated_status { + AccountStatus::Changed => { + let previous_storage = previous_storage_from_update(&updated_storage); + match self.status { + AccountStatus::Changed | AccountStatus::Loaded => { + // extend the storage. original values is not used inside bundle. + extend_storage(&mut self.storage, updated_storage); + } + AccountStatus::LoadedEmptyEIP161 => { + // Do nothing. + // Only change that can happen from LoadedEmpty to Changed is if balance + // is send to account. So we are only checking account change here. + } + _ => unreachable!("Invalid state transfer to Changed from {self:?}"), + }; + let previous_status = self.status; + self.status = AccountStatus::Changed; + self.info = updated_info; + Some(AccountRevert { + account: info_revert, + storage: previous_storage, + previous_status, + wipe_storage: false, + }) + } + AccountStatus::InMemoryChange => { + let previous_storage = previous_storage_from_update(&updated_storage); + let in_memory_info_revert = match self.status { + AccountStatus::Loaded | AccountStatus::InMemoryChange => { + // from loaded (Or LoadedEmpty) to InMemoryChange can happen if there is balance change + // or new created account but Loaded didn't have contract. + extend_storage(&mut self.storage, updated_storage); + info_revert + } + AccountStatus::LoadedEmptyEIP161 => { + self.storage = updated_storage; + info_revert + } + AccountStatus::LoadedNotExisting => { + self.storage = updated_storage; + AccountInfoRevert::DeleteIt + } + _ => unreachable!("Invalid change to InMemoryChange from {self:?}"), + }; + let previous_status = self.status; + self.status = AccountStatus::InMemoryChange; + self.info = updated_info; + Some(AccountRevert { + account: in_memory_info_revert, + storage: previous_storage, + previous_status, + wipe_storage: false, + }) + } + AccountStatus::Loaded + | AccountStatus::LoadedNotExisting + | AccountStatus::LoadedEmptyEIP161 => { + // No changeset, maybe just update data + // Do nothing for now. + None + } + AccountStatus::Destroyed => { + // clear this storage and move it to the Revert. + let this_storage = self.storage.drain().collect(); + let ret = match self.status { + AccountStatus::InMemoryChange | AccountStatus::Changed | AccountStatus::Loaded | AccountStatus::LoadedEmptyEIP161 => { + Some(AccountRevert::new_selfdestructed(self.status, info_revert, this_storage)) + } + AccountStatus::LoadedNotExisting => { + // Do nothing as we have LoadedNotExisting -> Destroyed (It is noop) + None + } + _ => unreachable!("Invalid transition to Destroyed account from: {self:?} to {updated_info:?} {updated_status:?}"), + }; + + if ret.is_some() { + self.status = AccountStatus::Destroyed; + self.info = None; + } + + // set present to destroyed. + ret + } + AccountStatus::DestroyedChanged => { + // Previous block created account or changed. + // (It was destroyed on previous block or one before). + + // check common pre destroy paths. + // If common path is there it will drain the storage. + if let Some(revert_state) = AccountRevert::new_selfdestructed_from_bundle( + info_revert.clone(), + self, + &updated_storage, + ) { + // set to destroyed and revert state. + self.status = AccountStatus::DestroyedChanged; + self.info = updated_info; + self.storage = updated_storage; + + Some(revert_state) + } else { + let ret = match self.status { + AccountStatus::Destroyed | AccountStatus::LoadedNotExisting => { + // from destroyed state new account is made + Some(AccountRevert { + account: AccountInfoRevert::DeleteIt, + storage: previous_storage_from_update(&updated_storage), + previous_status: self.status, + wipe_storage: false, + }) + } + AccountStatus::DestroyedChanged => { + // Account was destroyed in this transition. So we should clear present storage + // and insert it inside revert. + + let previous_storage = if transition.storage_was_destroyed { + let mut storage = core::mem::take(&mut self.storage) + .into_iter() + .map(|t| (t.0, RevertToSlot::Some(t.1.present_value))) + .collect::>(); + for key in updated_storage.keys() { + // as it is not existing inside Destroyed storage this means + // that previous values must be zero + storage.entry( *key).or_insert(RevertToSlot::Destroyed); + } + storage + } else { + previous_storage_from_update(&updated_storage) + }; + + Some(AccountRevert { + account: info_revert, + storage: previous_storage, + previous_status: AccountStatus::DestroyedChanged, + wipe_storage: false, + }) + } + AccountStatus::DestroyedAgain => { + Some(AccountRevert::new_selfdestructed_again( + // destroyed again will set empty account. + AccountStatus::DestroyedAgain, + AccountInfoRevert::DeleteIt, + HashMap::default(), + updated_storage.clone(), + )) + } + _ => unreachable!("Invalid state transfer to DestroyedNew from {self:?}"), + }; + self.status = AccountStatus::DestroyedChanged; + self.info = updated_info; + // extends current storage. + extend_storage(&mut self.storage, updated_storage); + + ret + } + } + AccountStatus::DestroyedAgain => { + // Previous block created account + // (It was destroyed on previous block or one before). + + // check common pre destroy paths. + // This will drain the storage if it is common transition. + let ret = if let Some(revert_state) = AccountRevert::new_selfdestructed_from_bundle( + info_revert, + self, + &HashMap::default(), + ) { + Some(revert_state) + } else { + match self.status { + AccountStatus::Destroyed + | AccountStatus::DestroyedAgain + | AccountStatus::LoadedNotExisting => { + // From destroyed to destroyed again. is noop + // + // DestroyedAgain to DestroyedAgain is noop + // + // From LoadedNotExisting to DestroyedAgain + // is noop as account is destroyed again + None + } + AccountStatus::DestroyedChanged => { + // From destroyed changed to destroyed again. + Some(AccountRevert::new_selfdestructed_again( + // destroyed again will set empty account. + AccountStatus::DestroyedChanged, + AccountInfoRevert::RevertTo(self.info.clone().unwrap_or_default()), + self.storage.drain().collect(), + HashMap::default(), + )) + } + _ => unreachable!("Invalid state to DestroyedAgain from {self:?}"), + } + }; + // set to destroyed and revert state. + self.status = AccountStatus::DestroyedAgain; + self.info = None; + self.storage.clear(); + ret + } + }; + + account_revert.and_then(|acc| if acc.is_empty() { None } else { Some(acc) }) + } + *) + Definition update_and_create_revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; transition ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let transition := M.alloc (| transition |) in + M.read (| + let~ updated_info := + M.copy (| + M.SubPointer.get_struct_record_field (| + transition, + "revm::db::states::transition_account::TransitionAccount", + "info" + |) + |) in + let~ updated_storage := + M.copy (| + M.SubPointer.get_struct_record_field (| + transition, + "revm::db::states::transition_account::TransitionAccount", + "storage" + |) + |) in + let~ updated_status := + M.copy (| + M.SubPointer.get_struct_record_field (| + transition, + "revm::db::states::transition_account::TransitionAccount", + "status" + |) + |) in + let~ extend_storage := + M.alloc (| + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let this_storage := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let storage_update := M.copy (| ฮณ |) in + M.read (| + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ M.read (| storage_update |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.break (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 1 + |) in + let key := + M.copy (| ฮณ1_0 |) in + let value := + M.copy (| ฮณ1_1 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::Entry") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + "or_insert", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.read (| + this_storage + |); + M.read (| key |) + ] + |); + M.read (| value |) + ] + |), + "revm_primitives::state::StorageSlot", + "present_value" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + value, + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + |) in + let~ previous_storage_from_update := + M.alloc (| + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let updated_storage := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "core::iter::adapters::filter::Filter") + [ + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + ] + ] + (Ty.path "bool") + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::filter::Filter") + [ + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + ] + ] + (Ty.path "bool") + ], + [], + "map", + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "filter", + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + ] + ] + (Ty.path "bool") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "iter", + [] + |), + [ M.read (| updated_storage |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let s := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::StorageSlot", + "is_changed", + [] + |), + [ + M.read (| + M.SubPointer.get_tuple_field (| + M.read (| s |), + 1 + |) + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let key := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| M.read (| key |) |); + Value.StructTuple + "revm::db::states::reverts::RevertToSlot::Some" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| value |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |) + |) + ] + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + |) in + let~ info_revert := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "ne", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |); + updated_info + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::RevertTo" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |) + ] + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DoNothing" + [] + |))) + ] + |) + |) in + let~ account_revert := + M.copy (| + M.match_operator (| + updated_status, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + let~ previous_storage := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + ] + ] + (Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ]), + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + ] + ], + "call", + [] + |), + [ previous_storage_from_update; Value.Tuple [ updated_storage ] ] + |) + |) in + let~ _ := + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ]; + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + ] + (Ty.tuple []), + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ]; + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + ], + "call", + [] + |), + [ + extend_storage; + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |); + M.read (| updated_storage |) + ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: Invalid state transfer to Changed from " + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ] + ] + |), + [ self ] + |) + ] + |)) + ] + |) + ] + |) + |) + |))) + ] + |) in + let~ previous_status := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Changed" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |), + M.read (| updated_info |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", M.read (| info_revert |)); + ("storage", M.read (| previous_storage |)); + ("previous_status", M.read (| previous_status |)); + ("wipe_storage", Value.Bool false) + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + let~ previous_storage := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + ] + ] + (Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ]), + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + ] + ], + "call", + [] + |), + [ previous_storage_from_update; Value.Tuple [ updated_storage ] ] + |) + |) in + let~ in_memory_info_revert := + M.copy (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ]; + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + ] + (Ty.tuple []), + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ]; + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + ], + "call", + [] + |), + [ + extend_storage; + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |); + M.read (| updated_storage |) + ] + ] + |) + |) in + info_revert + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |), + M.read (| updated_storage |) + |) in + info_revert)); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |), + M.read (| updated_storage |) + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: Invalid change to InMemoryChange from " + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ] + ] + |), + [ self ] + |) + ] + |)) + ] + |) + ] + |) + |) + |))) + ] + |) + |) in + let~ previous_status := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |), + M.read (| updated_info |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", M.read (| in_memory_info_revert |)); + ("storage", M.read (| previous_storage |)); + ("previous_status", M.read (| previous_status |)); + ("wipe_storage", Value.Bool false) + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple "core::option::Option::None" [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + let~ this_storage := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Drain") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "drain", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |) + ] + |) + |) in + let~ ret := + M.copy (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "new_selfdestructed", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + |); + M.read (| info_revert |); + M.read (| this_storage |) + ] + |) + ] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + M.alloc (| + Value.StructTuple "core::option::Option::None" [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: Invalid transition to Destroyed account from: " + |); + M.read (| Value.String " to " |); + M.read (| Value.String " " |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ] + ] + |), + [ self ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ] + |), + [ updated_info ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ + Ty.path + "revm::db::states::account_status::AccountStatus" + ] + |), + [ updated_status ] + |) + ] + |)) + ] + |) + ] + |) + |) + |))) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::reverts::AccountRevert" + ], + "is_some", + [] + |), + [ ret ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Destroyed" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |), + Value.StructTuple "core::option::Option::None" [] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + ret)); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::reverts::AccountRevert", + "new_selfdestructed_from_bundle", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm::db::states::reverts::AccountInfoRevert", + [], + "clone", + [] + |), + [ info_revert ] + |); + M.read (| self |); + updated_storage + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let revert_state := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |), + M.read (| updated_info |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |), + M.read (| updated_storage |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ M.read (| revert_state |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ ret := + M.copy (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + []); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + ] + ] + (Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ]), + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + ] + ], + "call", + [] + |), + [ + previous_storage_from_update; + Value.Tuple + [ updated_storage ] + ] + |)); + ("previous_status", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + |)); + ("wipe_storage", + Value.Bool false) + ] + ] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + let~ previous_storage := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + transition, + "revm::db::states::transition_account::TransitionAccount", + "storage_was_destroyed" + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ storage := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "map", + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ] + ] + ] + (Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_function (| + "core::mem::take", + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let t := + M.copy (| + ฮณ + |) in + Value.Tuple + [ + M.read (| + M.SubPointer.get_tuple_field (| + t, + 0 + |) + |); + Value.StructTuple + "revm::db::states::reverts::RevertToSlot::Some" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_tuple_field (| + t, + 1 + |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + ] + ])) + ] + |) + | _ => + M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::Keys") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "keys", + [] + |), + [ updated_storage ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := + M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::Keys") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.break (||) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let key := + M.copy (| + ฮณ0_0 + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::Entry") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ], + "or_insert", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + storage; + M.read (| + M.read (| + key + |) + |) + ] + |); + Value.StructTuple + "revm::db::states::reverts::RevertToSlot::Destroyed" + [] + ] + |) + |) in + M.alloc (| + Value.Tuple + [] + |))) + ] + |) in + M.alloc (| + Value.Tuple [] + |))) + |))) + ] + |)) in + storage)); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + ] + ] + (Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ]), + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + ] + ], + "call", + [] + |), + [ + previous_storage_from_update; + Value.Tuple [ updated_storage ] + ] + |) + |))) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", M.read (| info_revert |)); + ("storage", + M.read (| previous_storage |)); + ("previous_status", + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + []); + ("wipe_storage", Value.Bool false) + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "new_selfdestructed_again", + [] + |), + [ + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + []; + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + []; + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ updated_storage ] + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic_fmt", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: Invalid state transfer to DestroyedNew from " + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_debug", + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ] + ] + |), + [ self ] + |) + ] + |)) + ] + |) + ] + |) + |) + |))) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |), + M.read (| updated_info |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ]; + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + ] + (Ty.tuple []), + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ]; + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + ], + "call", + [] + |), + [ + extend_storage; + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |); + M.read (| updated_storage |) + ] + ] + |) + |) in + ret)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + let~ ret := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::reverts::AccountRevert", + "new_selfdestructed_from_bundle", + [] + |), + [ + M.read (| info_revert |); + M.read (| self |); + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |) + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let revert_state := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ M.read (| revert_state |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + Value.StructTuple + "core::option::Option::None" + [] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "new_selfdestructed_again", + [] + |), + [ + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + []; + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::RevertTo" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |) + ] + |) + ] + |) + ]; + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::Drain") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "collect", + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "drain", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |) + ] + |); + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic_fmt", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: Invalid state to DestroyedAgain from " + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_debug", + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ] + ] + |), + [ self ] + |) + ] + |)) + ] + |) + ] + |) + |) + |))) + ] + |))) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + Value.StructTuple + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + [] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |), + Value.StructTuple "core::option::Option::None" [] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "clear", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |) + |) in + ret)) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::reverts::AccountRevert" ], + "and_then", + [ + Ty.path "revm::db::states::reverts::AccountRevert"; + Ty.function + [ Ty.tuple [ Ty.path "revm::db::states::reverts::AccountRevert" ] ] + (Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::reverts::AccountRevert" ]) + ] + |), + [ + M.read (| account_revert |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let acc := M.copy (| ฮณ |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "is_empty", + [] + |), + [ acc ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple "core::option::Option::None" [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ M.read (| acc |) ] + |))) + ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_update_and_create_revert : + M.IsAssociatedFunction Self "update_and_create_revert" update_and_create_revert. + End Impl_revm_db_states_bundle_account_BundleAccount. + End bundle_account. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/bundle_state.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/bundle_state.md new file mode 100644 index 00000000..8d5dd795 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/bundle_state.md @@ -0,0 +1,9027 @@ +# ๐Ÿ“ bundle_state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/bundle_state.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module bundle_state. + (* StructRecord + { + name := "BundleBuilder"; + ty_params := []; + fields := + [ + ("states", + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ]); + ("state_original", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::AccountInfo"; + Ty.path "std::hash::random::RandomState" + ]); + ("state_present", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::AccountInfo"; + Ty.path "std::hash::random::RandomState" + ]); + ("state_storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "std::hash::random::RandomState" + ]; + Ty.path "std::hash::random::RandomState" + ]); + ("reverts", + Ty.apply + (Ty.path "alloc::collections::btree::set::BTreeSet") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.path "alloc::alloc::Global" + ]); + ("revert_range", + Ty.apply (Ty.path "core::ops::range::RangeInclusive") [ Ty.path "u64" ]); + ("revert_account", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "std::hash::random::RandomState" + ]); + ("revert_storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "std::hash::random::RandomState" + ]); + ("contracts", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ]) + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_db_states_bundle_state_BundleBuilder. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleBuilder". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "states" |); + M.read (| Value.String "state_original" |); + M.read (| Value.String "state_present" |); + M.read (| Value.String "state_storage" |); + M.read (| Value.String "reverts" |); + M.read (| Value.String "revert_range" |); + M.read (| Value.String "revert_account" |); + M.read (| Value.String "revert_storage" |); + M.read (| Value.String "contracts" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "states" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "state_original" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "state_present" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "state_storage" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "reverts" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "revert_range" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "revert_account" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "revert_storage" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "contracts" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "BundleBuilder" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_bundle_state_BundleBuilder. + + (* + Enum OriginalValuesKnown + { + ty_params := []; + variants := + [ + { + name := "Yes"; + item := StructTuple []; + discriminant := None; + }; + { + name := "No"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_marker_Copy_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_fmt_Debug_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::bundle_state::OriginalValuesKnown::Yes" + |) in + M.alloc (| M.read (| Value.String "Yes" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::bundle_state::OriginalValuesKnown::No" + |) in + M.alloc (| M.read (| Value.String "No" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::bundle_state::OriginalValuesKnown" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::bundle_state::OriginalValuesKnown" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)) |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_cmp_Eq_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_cmp_PartialOrd_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::bundle_state::OriginalValuesKnown" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::bundle_state::OriginalValuesKnown" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "isize", + [ Ty.path "isize" ], + "partial_cmp", + [] + |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_cmp_Ord_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::bundle_state::OriginalValuesKnown" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::bundle_state::OriginalValuesKnown" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::cmp::Ord", Ty.path "isize", [], "cmp", [] |), + [ __self_tag; __arg1_tag ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_hash_Hash_for_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::bundle_state::OriginalValuesKnown" ] + |), + [ M.read (| self |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "isize", + [], + "hash", + [ __H ] + |), + [ __self_tag; M.read (| state |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_revm_db_states_bundle_state_OriginalValuesKnown. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::OriginalValuesKnown". + + (* + pub fn is_not_known(&self) -> bool { + matches!(self, Self::No) + } + *) + Definition is_not_known (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::bundle_state::OriginalValuesKnown::No" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_not_known : + M.IsAssociatedFunction Self "is_not_known" is_not_known. + End Impl_revm_db_states_bundle_state_OriginalValuesKnown. + + Module Impl_core_default_Default_for_revm_db_states_bundle_state_BundleBuilder. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleBuilder". + + (* + fn default() -> Self { + BundleBuilder { + states: HashSet::new(), + state_original: HashMap::new(), + state_present: HashMap::new(), + state_storage: HashMap::new(), + reverts: BTreeSet::new(), + revert_range: 0..=0, + revert_account: HashMap::new(), + revert_storage: HashMap::new(), + contracts: HashMap::new(), + } + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::bundle_state::BundleBuilder" + [ + ("states", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("state_original", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::AccountInfo"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("state_present", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::AccountInfo"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("state_storage", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "std::hash::random::RandomState" + ]; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("reverts", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::collections::btree::set::BTreeSet") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |)); + ("revert_range", + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::ops::range::RangeInclusive") [ Ty.path "u64" ], + "new", + [] + |), + [ Value.Integer 0; Value.Integer 0 ] + |)); + ("revert_account", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("revert_storage", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("contracts", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_bundle_state_BundleBuilder. + + Module Impl_revm_db_states_bundle_state_BundleBuilder. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleBuilder". + + (* + pub fn new(revert_range: RangeInclusive) -> Self { + BundleBuilder { + revert_range, + ..Default::default() + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ revert_range ] => + ltac:(M.monadic + (let revert_range := M.alloc (| revert_range |) in + M.struct_record_update + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::states::bundle_state::BundleBuilder", + [], + "default", + [] + |), + [] + |)) + [ ("revert_range", M.read (| revert_range |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn state_address(mut self, address: Address) -> Self { + self.states.insert(address); + self + } + *) + Definition state_address (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "states" + |); + M.read (| address |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_state_address : + M.IsAssociatedFunction Self "state_address" state_address. + + (* + pub fn state_original_account_info(mut self, address: Address, original: AccountInfo) -> Self { + self.states.insert(address); + self.state_original.insert(address, original); + self + } + *) + Definition state_original_account_info (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; original ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let original := M.alloc (| original |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "states" + |); + M.read (| address |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::AccountInfo"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "state_original" + |); + M.read (| address |); + M.read (| original |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_state_original_account_info : + M.IsAssociatedFunction Self "state_original_account_info" state_original_account_info. + + (* + pub fn state_present_account_info(mut self, address: Address, present: AccountInfo) -> Self { + self.states.insert(address); + self.state_present.insert(address, present); + self + } + *) + Definition state_present_account_info (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; present ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let present := M.alloc (| present |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "states" + |); + M.read (| address |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::AccountInfo"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "state_present" + |); + M.read (| address |); + M.read (| present |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_state_present_account_info : + M.IsAssociatedFunction Self "state_present_account_info" state_present_account_info. + + (* + pub fn state_storage(mut self, address: Address, storage: HashMap) -> Self { + self.states.insert(address); + self.state_storage.insert(address, storage); + self + } + *) + Definition state_storage (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; storage ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let storage := M.alloc (| storage |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "states" + |); + M.read (| address |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "std::hash::random::RandomState" + ]; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "state_storage" + |); + M.read (| address |); + M.read (| storage |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_state_storage : + M.IsAssociatedFunction Self "state_storage" state_storage. + + (* + pub fn revert_address(mut self, block_number: u64, address: Address) -> Self { + self.reverts.insert((block_number, address)); + self + } + *) + Definition revert_address (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; block_number; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let block_number := M.alloc (| block_number |) in + let address := M.alloc (| address |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::collections::btree::set::BTreeSet") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.path "alloc::alloc::Global" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "reverts" + |); + Value.Tuple [ M.read (| block_number |); M.read (| address |) ] + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_revert_address : + M.IsAssociatedFunction Self "revert_address" revert_address. + + (* + pub fn revert_account_info( + mut self, + block_number: u64, + address: Address, + account: Option>, + ) -> Self { + self.reverts.insert((block_number, address)); + self.revert_account.insert((block_number, address), account); + self + } + *) + Definition revert_account_info (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; block_number; address; account ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let block_number := M.alloc (| block_number |) in + let address := M.alloc (| address |) in + let account := M.alloc (| account |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::collections::btree::set::BTreeSet") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.path "alloc::alloc::Global" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "reverts" + |); + Value.Tuple [ M.read (| block_number |); M.read (| address |) ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "revert_account" + |); + Value.Tuple [ M.read (| block_number |); M.read (| address |) ]; + M.read (| account |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_revert_account_info : + M.IsAssociatedFunction Self "revert_account_info" revert_account_info. + + (* + pub fn revert_storage( + mut self, + block_number: u64, + address: Address, + storage: Vec<(U256, U256)>, + ) -> Self { + self.reverts.insert((block_number, address)); + self.revert_storage.insert((block_number, address), storage); + self + } + *) + Definition revert_storage (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; block_number; address; storage ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let block_number := M.alloc (| block_number |) in + let address := M.alloc (| address |) in + let storage := M.alloc (| storage |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::collections::btree::set::BTreeSet") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.path "alloc::alloc::Global" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "reverts" + |); + Value.Tuple [ M.read (| block_number |); M.read (| address |) ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "revert_storage" + |); + Value.Tuple [ M.read (| block_number |); M.read (| address |) ]; + M.read (| storage |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_revert_storage : + M.IsAssociatedFunction Self "revert_storage" revert_storage. + + (* + pub fn contract(mut self, address: B256, bytecode: Bytecode) -> Self { + self.contracts.insert(address, bytecode); + self + } + *) + Definition contract (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; bytecode ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let bytecode := M.alloc (| bytecode |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "contracts" + |); + M.read (| address |); + M.read (| bytecode |) + ] + |) + |) in + self + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_contract : M.IsAssociatedFunction Self "contract" contract. + + (* + pub fn build(mut self) -> BundleState { + let mut state_size = 0; + let state = self + .states + .into_iter() + .map(|address| { + let storage = self + .state_storage + .remove(&address) + .map(|s| { + s.into_iter() + .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val))) + .collect() + }) + .unwrap_or_default(); + let bundle_account = BundleAccount::new( + self.state_original.remove(&address), + self.state_present.remove(&address), + storage, + AccountStatus::Changed, + ); + state_size += bundle_account.size_hint(); + (address, bundle_account) + }) + .collect(); + + let mut reverts_size = 0; + let mut reverts_map = BTreeMap::new(); + for block_number in self.revert_range { + reverts_map.insert(block_number, Vec::new()); + } + self.reverts + .into_iter() + .for_each(|(block_number, address)| { + let account = match self + .revert_account + .remove(&(block_number, address)) + .unwrap_or_default() + { + Some(Some(account)) => AccountInfoRevert::RevertTo(account), + Some(None) => AccountInfoRevert::DeleteIt, + None => AccountInfoRevert::DoNothing, + }; + let storage = self + .revert_storage + .remove(&(block_number, address)) + .map(|s| { + s.into_iter() + .map(|(k, v)| (k, RevertToSlot::Some(v))) + .collect() + }) + .unwrap_or_default(); + let account_revert = AccountRevert { + account, + storage, + previous_status: AccountStatus::Changed, + wipe_storage: false, + }; + + if reverts_map.contains_key(&block_number) { + reverts_size += account_revert.size_hint(); + reverts_map + .entry(block_number) + .or_insert(Vec::new()) + .push((address, account_revert)); + } + }); + + BundleState { + state, + contracts: self.contracts, + reverts: Reverts::new(reverts_map.into_values().collect()), + state_size, + reverts_size, + } + } + *) + Definition build (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ state_size := M.alloc (| Value.Integer 0 |) in + let~ state := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "std::collections::hash::set::IntoIter") + [ Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.function + [ Ty.tuple [ Ty.path "alloy_primitives::bits::address::Address" ] ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::set::IntoIter") + [ Ty.path "alloy_primitives::bits::address::Address" ], + [], + "map", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount" + ]; + Ty.function + [ Ty.tuple [ Ty.path "alloy_primitives::bits::address::Address" ] ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "states" + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let address := M.copy (| ฮณ |) in + M.read (| + let~ storage := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]; + Ty.path + "std::hash::random::RandomState" + ] + ], + "map", + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]; + Ty.path + "std::hash::random::RandomState" + ] + ] + ] + (Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]; + Ty.path + "std::hash::random::RandomState" + ]; + Ty.path + "std::hash::random::RandomState" + ], + "remove", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "state_storage" + |); + address + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let s := + M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path + "ruint::Uint"; + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ] + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ] + ] + ] + ] + (Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path + "ruint::Uint"; + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ] + ], + [], + "map", + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ] + ] + ] + ] + (Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ]; + Ty.path + "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ M.read (| s |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| + ฮฑ0 + |), + [ + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let + ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let + k := + M.copy (| + ฮณ0_0 + |) in + let + ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ0_1, + 0 + |) in + let + ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ0_1, + 1 + |) in + let + o_val := + M.copy (| + ฮณ1_0 + |) in + let + p_val := + M.copy (| + ฮณ1_1 + |) in + Value.Tuple + [ + M.read (| + k + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::StorageSlot", + "new_changed", + [] + |), + [ + M.read (| + o_val + |); + M.read (| + p_val + |) + ] + |) + ])) + ] + |) + | _ => + M.impossible (||) + end)) + ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ bundle_account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::AccountInfo"; + Ty.path + "std::hash::random::RandomState" + ], + "remove", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "state_original" + |); + address + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::AccountInfo"; + Ty.path + "std::hash::random::RandomState" + ], + "remove", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "state_present" + |); + address + ] + |); + M.read (| storage |); + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Changed" + [] + ] + |) + |) in + let~ _ := + let ฮฒ := state_size in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ bundle_account ] + |)) + |) in + M.alloc (| + Value.Tuple + [ + M.read (| address |); + M.read (| bundle_account |) + ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ reverts_size := M.alloc (| Value.Integer 0 |) in + let~ reverts_map := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply (Ty.path "core::ops::range::RangeInclusive") [ Ty.path "u64" ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "revert_range" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::ops::range::RangeInclusive") + [ Ty.path "u64" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let block_number := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "insert", + [] + |), + [ + reverts_map; + M.read (| block_number |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::collections::btree::set::IntoIter") + [ + Ty.tuple + [ Ty.path "u64"; Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "for_each", + [ + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::address::Address" + ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::collections::btree::set::BTreeSet") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::address::Address" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "reverts" + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let block_number := M.copy (| ฮณ0_0 |) in + let address := M.copy (| ฮณ0_1 |) in + M.read (| + let~ account := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ] + ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bits::address::Address" + ]; + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ]; + Ty.path + "std::hash::random::RandomState" + ], + "remove", + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bits::address::Address" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "revert_account" + |); + M.alloc (| + Value.Tuple + [ + M.read (| block_number |); + M.read (| address |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "core::option::Option::Some", + 0 + |) in + let account := M.copy (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::RevertTo" + [ M.read (| account |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let _ := + M.is_struct_tuple (| + ฮณ0_0, + "core::option::Option::None" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DoNothing" + [] + |))) + ] + |) + |) in + let~ storage := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ] + ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "map", + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + ] + (Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bits::address::Address" + ]; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path + "std::hash::random::RandomState" + ], + "remove", + [ + Ty.tuple + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bits::address::Address" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "revert_storage" + |); + M.alloc (| + Value.Tuple + [ + M.read (| block_number |); + M.read (| address |) + ] + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let s := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path + "alloc::vec::into_iter::IntoIter") + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ]; + Ty.path + "alloc::alloc::Global" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ] + ] + ] + (Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "alloc::vec::into_iter::IntoIter") + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "map", + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ] + ] + ] + (Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| s |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| + ฮฑ0 + |), + [ + fun ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let + ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let + k := + M.copy (| + ฮณ0_0 + |) in + let + v := + M.copy (| + ฮณ0_1 + |) in + Value.Tuple + [ + M.read (| + k + |); + Value.StructTuple + "revm::db::states::reverts::RevertToSlot::Some" + [ + M.read (| + v + |) + ] + ])) + ] + |) + | _ => + M.impossible (||) + end)) + ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ account_revert := + M.alloc (| + Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", M.read (| account |)); + ("storage", M.read (| storage |)); + ("previous_status", + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Changed" + []); + ("wipe_storage", Value.Bool false) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "contains_key", + [ Ty.path "u64" ] + |), + [ reverts_map; block_number ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := reverts_size in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "size_hint", + [] + |), + [ account_revert ] + |)) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::collections::btree::map::entry::Entry") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "or_insert", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "entry", + [] + |), + [ + reverts_map; + M.read (| block_number |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + ] + |); + Value.Tuple + [ + M.read (| address |); + M.read (| account_revert |) + ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::db::states::bundle_state::BundleState" + [ + ("state", M.read (| state |)); + ("contracts", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleBuilder", + "contracts" + |) + |)); + ("reverts", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::reverts::Reverts", + "new", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::collections::btree::map::IntoValues") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "collect", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "into_values", + [] + |), + [ M.read (| reverts_map |) ] + |) + ] + |) + ] + |)); + ("state_size", M.read (| state_size |)); + ("reverts_size", M.read (| reverts_size |)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_build : M.IsAssociatedFunction Self "build" build. + + (* + pub fn get_states(&self) -> &HashSet
{ + &self.states + } + *) + Definition get_states (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleBuilder", + "states" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_get_states : M.IsAssociatedFunction Self "get_states" get_states. + End Impl_revm_db_states_bundle_state_BundleBuilder. + + (* + Enum BundleRetention + { + ty_params := []; + variants := + [ + { + name := "PlainState"; + item := StructTuple []; + discriminant := None; + }; + { + name := "Reverts"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_db_states_bundle_state_BundleRetention. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleRetention". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ + M.read (| f |); + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::bundle_state::BundleRetention::PlainState" + |) in + M.alloc (| M.read (| Value.String "PlainState" |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::bundle_state::BundleRetention::Reverts" + |) in + M.alloc (| M.read (| Value.String "Reverts" |) |))) + ] + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_bundle_state_BundleRetention. + + Module Impl_revm_db_states_bundle_state_BundleRetention. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleRetention". + + (* + pub fn includes_reverts(&self) -> bool { + matches!(self, Self::Reverts) + } + *) + Definition includes_reverts (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::bundle_state::BundleRetention::Reverts" + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_includes_reverts : + M.IsAssociatedFunction Self "includes_reverts" includes_reverts. + End Impl_revm_db_states_bundle_state_BundleRetention. + + (* StructRecord + { + name := "BundleState"; + ty_params := []; + fields := + [ + ("state", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ]); + ("contracts", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ]); + ("reverts", Ty.path "revm::db::states::reverts::Reverts"); + ("state_size", Ty.path "usize"); + ("reverts_size", Ty.path "usize") + ]; + } *) + + Module Impl_core_default_Default_for_revm_db_states_bundle_state_BundleState. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleState". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::bundle_state::BundleState" + [ + ("state", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("contracts", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("reverts", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::states::reverts::Reverts", + [], + "default", + [] + |), + [] + |)); + ("state_size", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "usize", + [], + "default", + [] + |), + [] + |)); + ("reverts_size", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "usize", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_bundle_state_BundleState. + + Module Impl_core_clone_Clone_for_revm_db_states_bundle_state_BundleState. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleState". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::bundle_state::BundleState" + [ + ("state", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |) + ] + |)); + ("contracts", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "contracts" + |) + ] + |)); + ("reverts", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::db::states::reverts::Reverts", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |) + ] + |)); + ("state_size", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "usize", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) + ] + |)); + ("reverts_size", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "usize", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_bundle_state_BundleState. + + Module Impl_core_fmt_Debug_for_revm_db_states_bundle_state_BundleState. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleState". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field5_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "BundleState" |); + M.read (| Value.String "state" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |)); + M.read (| Value.String "contracts" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "contracts" + |)); + M.read (| Value.String "reverts" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |)); + M.read (| Value.String "state_size" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |)); + M.read (| Value.String "reverts_size" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_bundle_state_BundleState. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_bundle_state_BundleState. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_bundle_state_BundleState. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_bundle_state_BundleState. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleState". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::bundle_state::BundleState", + "state" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "contracts" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::bundle_state::BundleState", + "contracts" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::reverts::Reverts", + [ Ty.path "revm::db::states::reverts::Reverts" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_bundle_state_BundleState. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_bundle_state_BundleState. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_bundle_state_BundleState. + + Module Impl_core_cmp_Eq_for_revm_db_states_bundle_state_BundleState. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleState". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_bundle_state_BundleState. + + Module Impl_revm_db_states_bundle_state_BundleState. + Definition Self : Ty.t := Ty.path "revm::db::states::bundle_state::BundleState". + + (* + pub fn builder(revert_range: RangeInclusive) -> BundleBuilder { + BundleBuilder::new(revert_range) + } + *) + Definition builder (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ revert_range ] => + ltac:(M.monadic + (let revert_range := M.alloc (| revert_range |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleBuilder", + "new", + [] + |), + [ M.read (| revert_range |) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_builder : M.IsAssociatedFunction Self "builder" builder. + + (* + pub fn new( + state: impl IntoIterator< + Item = ( + Address, + Option, + Option, + HashMap, + ), + >, + reverts: impl IntoIterator< + Item = impl IntoIterator< + Item = ( + Address, + Option>, + impl IntoIterator, + ), + >, + >, + contracts: impl IntoIterator, + ) -> Self { + // Create state from iterator. + let mut state_size = 0; + let state = state + .into_iter() + .map(|(address, original, present, storage)| { + let account = BundleAccount::new( + original, + present, + storage + .into_iter() + .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val))) + .collect(), + AccountStatus::Changed, + ); + state_size += account.size_hint(); + (address, account) + }) + .collect(); + + // Create reverts from iterator. + let mut reverts_size = 0; + let reverts = reverts + .into_iter() + .map(|block_reverts| { + block_reverts + .into_iter() + .map(|(address, account, storage)| { + let account = match account { + Some(Some(account)) => AccountInfoRevert::RevertTo(account), + Some(None) => AccountInfoRevert::DeleteIt, + None => AccountInfoRevert::DoNothing, + }; + let revert = AccountRevert { + account, + storage: storage + .into_iter() + .map(|(k, v)| (k, RevertToSlot::Some(v))) + .collect(), + previous_status: AccountStatus::Changed, + wipe_storage: false, + }; + reverts_size += revert.size_hint(); + (address, revert) + }) + .collect::>() + }) + .collect::>(); + + Self { + state, + contracts: contracts.into_iter().collect(), + reverts: Reverts::new(reverts), + state_size, + reverts_size, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ + impl_IntoIterator_Item____Address__Option_AccountInfo___Option_AccountInfo___HashMap_U256___U256__U256____; + impl_IntoIterator_Item____U256__U256__; + impl_IntoIterator_Item____Address__Option_Option_AccountInfo____impl_IntoIterator_Item____U256__U256____; + impl_IntoIterator_Item___impl_IntoIterator_Item____Address__Option_Option_AccountInfo____impl_IntoIterator_Item____U256__U256_____; + impl_IntoIterator_Item____B256__Bytecode__ + ], + [ state; reverts; contracts ] => + ltac:(M.monadic + (let state := M.alloc (| state |) in + let reverts := M.alloc (| reverts |) in + let contracts := M.alloc (| contracts |) in + M.read (| + let~ state_size := M.alloc (| Value.Integer 0 |) in + let~ state := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.associated; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]; + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "std::hash::random::RandomState" + ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "map", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]; + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "std::hash::random::RandomState" + ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + impl_IntoIterator_Item____Address__Option_AccountInfo___Option_AccountInfo___HashMap_U256___U256__U256____, + [], + "into_iter", + [] + |), + [ M.read (| state |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_2 := M.SubPointer.get_tuple_field (| ฮณ, 2 |) in + let ฮณ0_3 := M.SubPointer.get_tuple_field (| ฮณ, 3 |) in + let address := M.copy (| ฮณ0_0 |) in + let original := M.copy (| ฮณ0_1 |) in + let present := M.copy (| ฮณ0_2 |) in + let storage := M.copy (| ฮณ0_3 |) in + M.read (| + let~ account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "new", + [] + |), + [ + M.read (| original |); + M.read (| present |); + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ] + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ] + ], + [], + "map", + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]; + Ty.path + "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ M.read (| storage |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let k := + M.copy (| ฮณ0_0 |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ0_1, + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ0_1, + 1 + |) in + let o_val := + M.copy (| ฮณ1_0 |) in + let p_val := + M.copy (| ฮณ1_1 |) in + Value.Tuple + [ + M.read (| k |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::StorageSlot", + "new_changed", + [] + |), + [ + M.read (| + o_val + |); + M.read (| + p_val + |) + ] + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |); + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Changed" + [] + ] + |) + |) in + let~ _ := + let ฮฒ := state_size in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ account ] + |)) + |) in + M.alloc (| + Value.Tuple + [ M.read (| address |); M.read (| account |) ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ reverts_size := M.alloc (| Value.Integer 0 |) in + let~ reverts := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.associated; + Ty.function + [ + Ty.tuple + [ + impl_IntoIterator_Item____Address__Option_Option_AccountInfo____impl_IntoIterator_Item____U256__U256____ + ] + ] + (Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "map", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.function + [ + Ty.tuple + [ + impl_IntoIterator_Item____Address__Option_Option_AccountInfo____impl_IntoIterator_Item____U256__U256____ + ] + ] + (Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + impl_IntoIterator_Item___impl_IntoIterator_Item____Address__Option_Option_AccountInfo____impl_IntoIterator_Item____U256__U256_____, + [], + "into_iter", + [] + |), + [ M.read (| reverts |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let block_reverts := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.associated; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ]; + impl_IntoIterator_Item____U256__U256__ + ] + ] + ] + (Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "map", + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ]; + impl_IntoIterator_Item____U256__U256__ + ] + ] + ] + (Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + impl_IntoIterator_Item____Address__Option_Option_AccountInfo____impl_IntoIterator_Item____U256__U256____, + [], + "into_iter", + [] + |), + [ M.read (| block_reverts |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let ฮณ0_2 := + M.SubPointer.get_tuple_field (| + ฮณ, + 2 + |) in + let address := + M.copy (| ฮณ0_0 |) in + let account := + M.copy (| ฮณ0_1 |) in + let storage := + M.copy (| ฮณ0_2 |) in + M.read (| + let~ account := + M.copy (| + M.match_operator (| + account, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "core::option::Option::Some", + 0 + |) in + let account := + M.copy (| + ฮณ1_0 + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::RevertTo" + [ + M.read (| + account + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let _ := + M.is_struct_tuple (| + ฮณ0_0, + "core::option::Option::None" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DoNothing" + [] + |))) + ] + |) + |) in + let~ revert := + M.alloc (| + Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", + M.read (| + account + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "core::iter::adapters::map::Map") + [ + Ty.associated; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ] + ] + ] + (Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "map", + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ] + ] + ] + (Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + impl_IntoIterator_Item____U256__U256__, + [], + "into_iter", + [] + |), + [ + M.read (| + storage + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match + ฮณ + with + | [ ฮฑ0 + ] => + M.match_operator (| + M.alloc (| + ฮฑ0 + |), + [ + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let + ฮณ0_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let + k := + M.copy (| + ฮณ0_0 + |) in + let + v := + M.copy (| + ฮณ0_1 + |) in + Value.Tuple + [ + M.read (| + k + |); + Value.StructTuple + "revm::db::states::reverts::RevertToSlot::Some" + [ + M.read (| + v + |) + ] + ])) + ] + |) + | _ => + M.impossible (||) + end)) + ] + |) + ] + |)); + ("previous_status", + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Changed" + []); + ("wipe_storage", + Value.Bool false) + ] + |) in + let~ _ := + let ฮฒ := reverts_size in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "size_hint", + [] + |), + [ revert ] + |)) + |) in + M.alloc (| + Value.Tuple + [ + M.read (| address |); + M.read (| revert |) + ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::db::states::bundle_state::BundleState" + [ + ("state", M.read (| state |)); + ("contracts", + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + impl_IntoIterator_Item____B256__Bytecode__, + [], + "into_iter", + [] + |), + [ M.read (| contracts |) ] + |) + ] + |)); + ("reverts", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::reverts::Reverts", + "new", + [] + |), + [ M.read (| reverts |) ] + |)); + ("state_size", M.read (| state_size |)); + ("reverts_size", M.read (| reverts_size |)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn size_hint(&self) -> usize { + self.state_size + self.reverts_size + self.contracts.len() + } + *) + Definition size_hint (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.add + Integer.Usize + (BinOp.Wrap.add + Integer.Usize + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |) + |))) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "contracts" + |) + ] + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_size_hint : M.IsAssociatedFunction Self "size_hint" size_hint. + + (* + pub fn state(&self) -> &HashMap { + &self.state + } + *) + Definition state (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_state : M.IsAssociatedFunction Self "state" state. + + (* + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + *) + Definition is_empty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleState", + "len", + [] + |), + [ M.read (| self |) ] + |)) + (Value.Integer 0))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_empty : M.IsAssociatedFunction Self "is_empty" is_empty. + + (* + pub fn len(&self) -> usize { + self.state.len() + } + *) + Definition len (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_len : M.IsAssociatedFunction Self "len" len. + + (* + pub fn account(&self, address: &Address) -> Option<&BundleAccount> { + self.state.get(address) + } + *) + Definition account (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_account : M.IsAssociatedFunction Self "account" account. + + (* + pub fn bytecode(&self, hash: &B256) -> Option { + self.contracts.get(hash).cloned() + } + *) + Definition bytecode (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let hash := M.alloc (| hash |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::bytecode::Bytecode" ] ], + "cloned", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "contracts" + |); + M.read (| hash |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_bytecode : M.IsAssociatedFunction Self "bytecode" bytecode. + + (* + pub fn apply_transitions_and_create_reverts( + &mut self, + transitions: TransitionState, + retention: BundleRetention, + ) { + let include_reverts = retention.includes_reverts(); + // pessimistically pre-allocate assuming _all_ accounts changed. + let reverts_capacity = if include_reverts { + transitions.transitions.len() + } else { + 0 + }; + let mut reverts = Vec::with_capacity(reverts_capacity); + + for (address, transition) in transitions.transitions.into_iter() { + // add new contract if it was created/changed. + if let Some((hash, new_bytecode)) = transition.has_new_contract() { + self.contracts.insert(hash, new_bytecode.clone()); + } + // update state and create revert. + let revert = match self.state.entry(address) { + hash_map::Entry::Occupied(mut entry) => { + let entry = entry.get_mut(); + self.state_size -= entry.size_hint(); + // update and create revert if it is present + let revert = entry.update_and_create_revert(transition); + // update the state size + self.state_size += entry.size_hint(); + revert + } + hash_map::Entry::Vacant(entry) => { + // make revert from transition account + let present_bundle = transition.present_bundle_account(); + let revert = transition.create_revert(); + if revert.is_some() { + self.state_size += present_bundle.size_hint(); + entry.insert(present_bundle); + } + revert + } + }; + + // append revert if present. + if let Some(revert) = revert.filter(|_| include_reverts) { + self.reverts_size += revert.size_hint(); + reverts.push((address, revert)); + } + } + + self.reverts.push(reverts); + } + *) + Definition apply_transitions_and_create_reverts (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; transitions; retention ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let transitions := M.alloc (| transitions |) in + let retention := M.alloc (| retention |) in + M.read (| + let~ include_reverts := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleRetention", + "includes_reverts", + [] + |), + [ retention ] + |) + |) in + let~ reverts_capacity := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use include_reverts in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + transitions, + "revm::db::states::transition_state::TransitionState", + "transitions" + |) + ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Integer 0 |))) + ] + |) + |) in + let~ reverts := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ M.read (| reverts_capacity |) ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount" + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + transitions, + "revm::db::states::transition_state::TransitionState", + "transitions" + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let address := M.copy (| ฮณ1_0 |) in + let transition := M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::transition_account::TransitionAccount", + "has_new_contract", + [] + |), + [ transition ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let hash := M.copy (| ฮณ1_0 |) in + let new_bytecode := M.copy (| ฮณ1_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path + "revm_primitives::bytecode::Bytecode"; + Ty.path + "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "contracts" + |); + M.read (| hash |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ M.read (| new_bytecode |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ revert := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ entry := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + "get_mut", + [] + |), + [ entry ] + |) + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.sub + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ M.read (| entry |) ] + |)) + |) in + let~ revert := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "update_and_create_revert", + [] + |), + [ + M.read (| entry |); + M.read (| transition |) + ] + |) + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ M.read (| entry |) ] + |)) + |) in + revert)); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ present_bundle := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::transition_account::TransitionAccount", + "present_bundle_account", + [] + |), + [ transition ] + |) + |) in + let~ revert := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::transition_account::TransitionAccount", + "create_revert", + [] + |), + [ M.read (| transition |) ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.path + "revm::db::states::reverts::AccountRevert" + ], + "is_some", + [] + |), + [ revert ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ present_bundle ] + |)) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.read (| present_bundle |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + revert)) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::reverts::AccountRevert" + ], + "filter", + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm::db::states::reverts::AccountRevert" + ] + ] + ] + (Ty.path "bool") + ] + |), + [ + M.read (| revert |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.read (| + include_reverts + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let revert := M.copy (| ฮณ0_0 |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "size_hint", + [] + |), + [ revert ] + |)) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + reverts; + Value.Tuple + [ + M.read (| address |); + M.read (| revert |) + ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.path "revm::db::states::reverts::Reverts", + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |) + ] + |); + M.read (| reverts |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_apply_transitions_and_create_reverts : + M.IsAssociatedFunction + Self + "apply_transitions_and_create_reverts" + apply_transitions_and_create_reverts. + + (* + pub fn into_plain_state(self, is_value_known: OriginalValuesKnown) -> StateChangeset { + // pessimistically pre-allocate assuming _all_ accounts changed. + let state_len = self.state.len(); + let mut accounts = Vec::with_capacity(state_len); + let mut storage = Vec::with_capacity(state_len); + + for (address, account) in self.state { + // append account info if it is changed. + let was_destroyed = account.was_destroyed(); + if is_value_known.is_not_known() || account.is_info_changed() { + let info = account.info.map(AccountInfo::without_code); + accounts.push((address, info)); + } + + // append storage changes + + // NOTE: Assumption is that revert is going to remove whole plain storage from + // database so we can check if plain state was wiped or not. + let mut account_storage_changed = Vec::with_capacity(account.storage.len()); + + for (key, slot) in account.storage { + // If storage was destroyed that means that storage was wiped. + // In that case we need to check if present storage value is different then ZERO. + let destroyed_and_not_zero = was_destroyed && slot.present_value != U256::ZERO; + + // If account is not destroyed check if original values was changed, + // so we can update it. + let not_destroyed_and_changed = !was_destroyed && slot.is_changed(); + + if is_value_known.is_not_known() + || destroyed_and_not_zero + || not_destroyed_and_changed + { + account_storage_changed.push((key, slot.present_value)); + } + } + + if !account_storage_changed.is_empty() || was_destroyed { + // append storage changes to account. + storage.push(PlainStorageChangeset { + address, + wipe_storage: was_destroyed, + storage: account_storage_changed, + }); + } + } + let contracts = self + .contracts + .into_iter() + // remove empty bytecodes + .filter(|(b, _)| *b != KECCAK_EMPTY) + .collect::>(); + StateChangeset { + accounts, + storage, + contracts, + } + } + *) + Definition into_plain_state (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; is_value_known ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let is_value_known := M.alloc (| is_value_known |) in + M.read (| + let~ state_len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleState", + "state" + |) + ] + |) + |) in + let~ accounts := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ M.read (| state_len |) ] + |) + |) in + let~ storage := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::db::states::changes::PlainStorageChangeset"; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ M.read (| state_len |) ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleState", + "state" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let address := M.copy (| ฮณ1_0 |) in + let account := M.copy (| ฮณ1_1 |) in + let~ was_destroyed := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "was_destroyed", + [] + |), + [ account ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_state::OriginalValuesKnown", + "is_not_known", + [] + |), + [ is_value_known ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "is_info_changed", + [] + |), + [ account ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ], + "map", + [ + Ty.path + "revm_primitives::state::AccountInfo"; + Ty.function + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + (Ty.path + "revm_primitives::state::AccountInfo") + ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm::db::states::bundle_account::BundleAccount", + "info" + |) + |); + M.get_associated_function (| + Ty.path + "revm_primitives::state::AccountInfo", + "without_code", + [] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + accounts; + Value.Tuple + [ + M.read (| address |); + M.read (| info |) + ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ account_storage_changed := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + account, + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.break (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 1 + |) in + let key := M.copy (| ฮณ1_0 |) in + let slot := M.copy (| ฮณ1_1 |) in + let~ destroyed_and_not_zero := + M.alloc (| + LogicalOp.and (| + M.read (| + was_destroyed + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "ruint::Uint", + [ + Ty.path + "ruint::Uint" + ], + "ne", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + slot, + "revm_primitives::state::StorageSlot", + "present_value" + |); + M.get_constant (| + "ruint::ZERO" + |) + ] + |))) + |) + |) in + let~ + not_destroyed_and_changed := + M.alloc (| + LogicalOp.and (| + UnOp.Pure.not + (M.read (| + was_destroyed + |)), + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::StorageSlot", + "is_changed", + [] + |), + [ slot ] + |))) + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_state::OriginalValuesKnown", + "is_not_known", + [] + |), + [ + is_value_known + ] + |), + ltac:(M.monadic + (M.read (| + destroyed_and_not_zero + |))) + |), + ltac:(M.monadic + (M.read (| + not_destroyed_and_changed + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ]; + Ty.path + "alloc::alloc::Global" + ], + "push", + [] + |), + [ + account_storage_changed; + Value.Tuple + [ + M.read (| + key + |); + M.read (| + M.SubPointer.get_struct_record_field (| + slot, + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + ] + ] + |) + |) in + M.alloc (| + Value.Tuple [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint" + ]; + Ty.path "alloc::alloc::Global" + ], + "is_empty", + [] + |), + [ account_storage_changed ] + |)), + ltac:(M.monadic + (M.read (| was_destroyed |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm::db::states::changes::PlainStorageChangeset"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + storage; + Value.StructRecord + "revm::db::states::changes::PlainStorageChangeset" + [ + ("address", M.read (| address |)); + ("wipe_storage", + M.read (| was_destroyed |)); + ("storage", + M.read (| + account_storage_changed + |)) + ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ contracts := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::filter::Filter") + [ + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ] + ] + ] + ] + (Ty.path "bool") + ], + [], + "collect", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ], + [], + "filter", + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ] + ] + ] + ] + (Ty.path "bool") + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::bundle_state::BundleState", + "contracts" + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let b := M.alloc (| ฮณ1_0 |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ], + "ne", + [] + |), + [ + M.read (| b |); + M.get_constant (| + "revm_primitives::utilities::KECCAK_EMPTY" + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::db::states::changes::StateChangeset" + [ + ("accounts", M.read (| accounts |)); + ("storage", M.read (| storage |)); + ("contracts", M.read (| contracts |)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_plain_state : + M.IsAssociatedFunction Self "into_plain_state" into_plain_state. + + (* + pub fn into_plain_state_and_reverts( + mut self, + is_value_known: OriginalValuesKnown, + ) -> (StateChangeset, PlainStateReverts) { + let reverts = self.take_all_reverts(); + let plain_state = self.into_plain_state(is_value_known); + (plain_state, reverts.into_plain_state_reverts()) + } + *) + Definition into_plain_state_and_reverts (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; is_value_known ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let is_value_known := M.alloc (| is_value_known |) in + M.read (| + let~ reverts := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleState", + "take_all_reverts", + [] + |), + [ self ] + |) + |) in + let~ plain_state := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleState", + "into_plain_state", + [] + |), + [ M.read (| self |); M.read (| is_value_known |) ] + |) + |) in + M.alloc (| + Value.Tuple + [ + M.read (| plain_state |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::reverts::Reverts", + "into_plain_state_reverts", + [] + |), + [ M.read (| reverts |) ] + |) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_plain_state_and_reverts : + M.IsAssociatedFunction Self "into_plain_state_and_reverts" into_plain_state_and_reverts. + + (* + pub fn extend_state(&mut self, other_state: HashMap) { + for (address, other_account) in other_state { + match self.state.entry(address) { + hash_map::Entry::Occupied(mut entry) => { + let this = entry.get_mut(); + self.state_size -= this.size_hint(); + + // if other was destroyed. replace `this` storage with + // the `other one. + if other_account.was_destroyed() { + this.storage = other_account.storage; + } else { + // otherwise extend this storage with other + for (key, storage_slot) in other_account.storage { + // update present value or insert storage slot. + this.storage + .entry(key) + .or_insert(storage_slot) + .present_value = storage_slot.present_value; + } + } + this.info = other_account.info; + this.status.transition(other_account.status); + + // Update the state size + self.state_size += this.size_hint(); + } + hash_map::Entry::Vacant(entry) => { + // just insert if empty + self.state_size += other_account.size_hint(); + entry.insert(other_account); + } + } + } + } + *) + Definition extend_state (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other_state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other_state := M.alloc (| other_state |) in + M.read (| + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ M.read (| other_state |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let address := M.copy (| ฮณ1_0 |) in + let other_account := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ this := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + "get_mut", + [] + |), + [ entry ] + |) + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.sub + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ M.read (| this |) ] + |)) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "was_destroyed", + [] + |), + [ other_account ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| this |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + other_account, + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + other_account, + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.break (||) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 1 + |) in + let key := + M.copy (| + ฮณ1_0 + |) in + let + storage_slot := + M.copy (| + ฮณ1_1 + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::Entry") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + "or_insert", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + this + |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |); + M.read (| + key + |) + ] + |); + M.read (| + storage_slot + |) + ] + |), + "revm_primitives::state::StorageSlot", + "present_value" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + storage_slot, + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + |) in + M.alloc (| + Value.Tuple [] + |))) + ] + |) in + M.alloc (| + Value.Tuple [] + |))) + |))) + ] + |)))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| this |), + "revm::db::states::bundle_account::BundleAccount", + "info" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + other_account, + "revm::db::states::bundle_account::BundleAccount", + "info" + |) + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::account_status::AccountStatus", + "transition", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| this |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + other_account, + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + |) + ] + |) + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ M.read (| this |) ] + |)) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ other_account ] + |)) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.read (| other_account |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_extend_state : + M.IsAssociatedFunction Self "extend_state" extend_state. + + (* + pub fn extend(&mut self, mut other: Self) { + // iterate over reverts and if its storage is wiped try to add previous bundle + // state as there is potential missing slots. + for (address, revert) in other.reverts.iter_mut().flatten() { + if revert.wipe_storage { + // If there is wipe storage in `other` revert + // we need to move storage from present state. + if let Some(this_account) = self.state.get_mut(address) { + // As this account was destroyed inside `other` bundle. + // we are fine to wipe/drain this storage and put it inside revert. + for (key, value) in this_account.storage.drain() { + revert + .storage + .entry(key) + .or_insert(RevertToSlot::Some(value.present_value)); + } + + // nullify `other` wipe as primary database wipe is done in `this`. + if this_account.was_destroyed() { + revert.wipe_storage = false; + } + } + } + + // Increment reverts size for each of the updated reverts. + self.reverts_size += revert.size_hint(); + } + // Extension of state + self.extend_state(other.state); + // Contract can be just extended, when counter is introduced we will take into account that. + self.contracts.extend(other.contracts); + // Reverts can be just extended + self.reverts.extend(other.reverts); + } + *) + Definition extend (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::iter::adapters::flatten::Flatten") + [ + Ty.apply + (Ty.path "core::slice::iter::IterMut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::IterMut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "flatten", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "iter_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.path "revm::db::states::reverts::Reverts", + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::bundle_state::BundleState", + "reverts" + |) + ] + |) + ] + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::flatten::Flatten") + [ + Ty.apply + (Ty.path "core::slice::iter::IterMut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ2_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let address := M.alloc (| ฮณ2_0 |) in + let revert := M.alloc (| ฮณ2_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| revert |), + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount"; + Ty.path + "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |); + M.read (| address |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let this_account := M.copy (| ฮณ0_0 |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::Drain") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "drain", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + this_account + |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := + M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::Drain") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.break (||) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 1 + |) in + let key := + M.copy (| + ฮณ1_0 + |) in + let value := + M.copy (| + ฮณ1_1 + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::Entry") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ], + "or_insert", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + revert + |), + "revm::db::states::reverts::AccountRevert", + "storage" + |); + M.read (| + key + |) + ] + |); + Value.StructTuple + "revm::db::states::reverts::RevertToSlot::Some" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + value, + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + ] + ] + |) + |) in + M.alloc (| + Value.Tuple + [] + |))) + ] + |) in + M.alloc (| + Value.Tuple [] + |))) + |))) + ] + |)) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "was_destroyed", + [] + |), + [ + M.read (| + this_account + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| revert |), + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |), + Value.Bool false + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "size_hint", + [] + |), + [ M.read (| revert |) ] + |)) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleState", + "extend_state", + [] + |), + [ + M.read (| self |); + M.read (| + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::bundle_state::BundleState", + "state" + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::Extend", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ] + ], + "extend", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "contracts" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::bundle_state::BundleState", + "contracts" + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::reverts::Reverts", + "extend", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::bundle_state::BundleState", + "reverts" + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_extend : M.IsAssociatedFunction Self "extend" extend. + + (* + pub fn take_n_reverts(&mut self, reverts_to_take: usize) -> Reverts { + // split is done as [0, num) and [num, len]. + if reverts_to_take > self.reverts.len() { + return self.take_all_reverts(); + } + let (detach, this) = self.reverts.split_at(reverts_to_take); + let detached_reverts = Reverts::new(detach.to_vec()); + self.reverts_size = this + .iter() + .flatten() + .fold(0, |acc, (_, revert)| acc + revert.size_hint()); + self.reverts = Reverts::new(this.to_vec()); + detached_reverts + } + *) + Definition take_n_reverts (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; reverts_to_take ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let reverts_to_take := M.alloc (| reverts_to_take |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| reverts_to_take |)) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "revm::db::states::reverts::Reverts", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |) + ] + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleState", + "take_all_reverts", + [] + |), + [ M.read (| self |) ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "split_at", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "revm::db::states::reverts::Reverts", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |) + ] + |) + ] + |); + M.read (| reverts_to_take |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let detach := M.copy (| ฮณ0_0 |) in + let this := M.copy (| ฮณ0_1 |) in + let~ detached_reverts := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::reverts::Reverts", + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "to_vec", + [] + |), + [ M.read (| detach |) ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |), + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::flatten::Flatten") + [ + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + ], + [], + "fold", + [ + Ty.path "usize"; + Ty.function + [ + Ty.tuple + [ + Ty.path "usize"; + Ty.apply + (Ty.path "&") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ] + ] + ] + ] + (Ty.path "usize") + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "flatten", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "iter", + [] + |), + [ M.read (| this |) ] + |) + ] + |); + Value.Integer 0; + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let acc := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let revert := M.alloc (| ฮณ1_1 |) in + BinOp.Wrap.add + Integer.Usize + (M.read (| acc |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "size_hint", + [] + |), + [ M.read (| revert |) ] + |)))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::reverts::Reverts", + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "to_vec", + [] + |), + [ M.read (| this |) ] + |) + ] + |) + |) in + detached_reverts)) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_take_n_reverts : + M.IsAssociatedFunction Self "take_n_reverts" take_n_reverts. + + (* + pub fn take_all_reverts(&mut self) -> Reverts { + self.reverts_size = 0; + core::mem::take(&mut self.reverts) + } + *) + Definition take_all_reverts (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |), + Value.Integer 0 + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::take", + [ Ty.path "revm::db::states::reverts::Reverts" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_take_all_reverts : + M.IsAssociatedFunction Self "take_all_reverts" take_all_reverts. + + (* + pub fn revert_latest(&mut self) -> bool { + // revert the latest recorded state + if let Some(reverts) = self.reverts.pop() { + for (address, revert_account) in reverts.into_iter() { + self.reverts_size -= revert_account.size_hint(); + match self.state.entry(address) { + Entry::Occupied(mut entry) => { + let account = entry.get_mut(); + self.state_size -= account.size_hint(); + if account.revert(revert_account) { + entry.remove(); + } else { + self.state_size += account.size_hint(); + } + } + Entry::Vacant(entry) => { + // create empty account that we will revert on. + // Only place where this account is not existing is if revert is DeleteIt. + let mut account = BundleAccount::new( + None, + None, + HashMap::new(), + AccountStatus::LoadedNotExisting, + ); + if !account.revert(revert_account) { + self.state_size += account.size_hint(); + entry.insert(account); + } + } + } + } + return true; + } + + false + } + *) + Definition revert_latest (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "pop", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.path "revm::db::states::reverts::Reverts", + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts" + |) + ] + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let reverts := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| reverts |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "alloc::vec::into_iter::IntoIter") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.break (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 1 + |) in + let address := M.copy (| ฮณ1_0 |) in + let revert_account := + M.copy (| ฮณ1_1 |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "reverts_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.sub + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::reverts::AccountRevert", + "size_hint", + [] + |), + [ revert_account ] + |)) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount"; + Ty.path + "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := + M.copy (| ฮณ0_0 |) in + let~ account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + "get_mut", + [] + |), + [ entry ] + |) + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.sub + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ M.read (| account |) + ] + |)) + |) in + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "revert", + [] + |), + [ + M.read (| + account + |); + M.read (| + revert_account + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + "remove", + [] + |), + [ + M.read (| + entry + |) + ] + |) + |) in + M.alloc (| + Value.Tuple [] + |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| + self + |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ + M.read (| + account + |) + ] + |)) + |) in + M.alloc (| + Value.Tuple [] + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := + M.copy (| ฮณ0_0 |) in + let~ account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "new", + [] + |), + [ + Value.StructTuple + "core::option::Option::None" + []; + Value.StructTuple + "core::option::Option::None" + []; + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |); + Value.StructTuple + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + [] + ] + |) + |) in + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "revert", + [] + |), + [ + account; + M.read (| + revert_account + |) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| + self + |), + "revm::db::states::bundle_state::BundleState", + "state_size" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.add + Integer.Usize + (M.read (| ฮฒ |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_account::BundleAccount", + "size_hint", + [] + |), + [ account ] + |)) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + "insert", + [] + |), + [ + M.read (| + entry + |); + M.read (| + account + |) + ] + |) + |) in + M.alloc (| + Value.Tuple [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.return_ (| Value.Bool true |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Bool false |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_revert_latest : + M.IsAssociatedFunction Self "revert_latest" revert_latest. + + (* + pub fn revert(&mut self, mut num_transitions: usize) { + if num_transitions == 0 { + return; + } + + while self.revert_latest() { + num_transitions -= 1; + if num_transitions == 0 { + // break the loop. + break; + } + } + } + *) + Definition revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; num_transitions ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let num_transitions := M.alloc (| num_transitions |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| num_transitions |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| M.read (| M.return_ (| Value.Tuple [] |) |) |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleState", + "revert_latest", + [] + |), + [ M.read (| self |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + let ฮฒ := num_transitions in + M.write (| + ฮฒ, + BinOp.Wrap.sub Integer.Usize (M.read (| ฮฒ |)) (Value.Integer 1) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| num_transitions |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_revert : M.IsAssociatedFunction Self "revert" revert. + + (* + pub fn prepend_state(&mut self, mut other: BundleState) { + // take this bundle + let this_bundle = mem::take(self); + // extend other bundle state with this + other.extend_state(this_bundle.state); + // extend other contracts + other.contracts.extend(this_bundle.contracts); + // swap bundles + mem::swap(self, &mut other) + } + *) + Definition prepend_state (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ this_bundle := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::take", + [ Ty.path "revm::db::states::bundle_state::BundleState" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleState", + "extend_state", + [] + |), + [ + other; + M.read (| + M.SubPointer.get_struct_record_field (| + this_bundle, + "revm::db::states::bundle_state::BundleState", + "state" + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::Extend", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ] + ], + "extend", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::bundle_state::BundleState", + "contracts" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + this_bundle, + "revm::db::states::bundle_state::BundleState", + "contracts" + |) + |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::swap", + [ Ty.path "revm::db::states::bundle_state::BundleState" ] + |), + [ M.read (| self |); other ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_prepend_state : + M.IsAssociatedFunction Self "prepend_state" prepend_state. + End Impl_revm_db_states_bundle_state_BundleState. + End bundle_state. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/cache.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/cache.md new file mode 100644 index 00000000..503e8528 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/cache.md @@ -0,0 +1,1523 @@ +# ๐Ÿ“ cache.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/cache.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module cache. + (* StructRecord + { + name := "CacheState"; + ty_params := []; + fields := + [ + ("accounts", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ]); + ("contracts", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ]); + ("has_state_clear", Ty.path "bool") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_cache_CacheState. + Definition Self : Ty.t := Ty.path "revm::db::states::cache::CacheState". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::cache::CacheState" + [ + ("accounts", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "accounts" + |) + ] + |)); + ("contracts", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "contracts" + |) + ] + |)); + ("has_state_clear", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "has_state_clear" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_cache_CacheState. + + Module Impl_core_fmt_Debug_for_revm_db_states_cache_CacheState. + Definition Self : Ty.t := Ty.path "revm::db::states::cache::CacheState". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CacheState" |); + M.read (| Value.String "accounts" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "accounts" + |)); + M.read (| Value.String "contracts" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "contracts" + |)); + M.read (| Value.String "has_state_clear" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "has_state_clear" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_cache_CacheState. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_cache_CacheState. + Definition Self : Ty.t := Ty.path "revm::db::states::cache::CacheState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_cache_CacheState. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_cache_CacheState. + Definition Self : Ty.t := Ty.path "revm::db::states::cache::CacheState". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "accounts" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::cache::CacheState", + "accounts" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "contracts" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::cache::CacheState", + "contracts" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "has_state_clear" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::cache::CacheState", + "has_state_clear" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_cache_CacheState. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_cache_CacheState. + Definition Self : Ty.t := Ty.path "revm::db::states::cache::CacheState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_cache_CacheState. + + Module Impl_core_cmp_Eq_for_revm_db_states_cache_CacheState. + Definition Self : Ty.t := Ty.path "revm::db::states::cache::CacheState". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_cache_CacheState. + + Module Impl_core_default_Default_for_revm_db_states_cache_CacheState. + Definition Self : Ty.t := Ty.path "revm::db::states::cache::CacheState". + + (* + fn default() -> Self { + Self::new(true) + } + *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache::CacheState", + "new", + [] + |), + [ Value.Bool true ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_cache_CacheState. + + Module Impl_revm_db_states_cache_CacheState. + Definition Self : Ty.t := Ty.path "revm::db::states::cache::CacheState". + + (* + pub fn new(has_state_clear: bool) -> Self { + Self { + accounts: HashMap::default(), + contracts: HashMap::default(), + has_state_clear, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ has_state_clear ] => + ltac:(M.monadic + (let has_state_clear := M.alloc (| has_state_clear |) in + Value.StructRecord + "revm::db::states::cache::CacheState" + [ + ("accounts", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("contracts", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("has_state_clear", M.read (| has_state_clear |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn set_state_clear_flag(&mut self, has_state_clear: bool) { + self.has_state_clear = has_state_clear; + } + *) + Definition set_state_clear_flag (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; has_state_clear ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let has_state_clear := M.alloc (| has_state_clear |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "has_state_clear" + |), + M.read (| has_state_clear |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_state_clear_flag : + M.IsAssociatedFunction Self "set_state_clear_flag" set_state_clear_flag. + + (* + pub fn trie_account(&self) -> impl IntoIterator { + self.accounts.iter().filter_map(|(address, account)| { + account + .account + .as_ref() + .map(|plain_acc| ( *address, plain_acc)) + }) + } + *) + Definition trie_account (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount" + ], + [], + "filter_map", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::address::Address" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::cache_account::CacheAccount" ] + ] + ] + ] + (Ty.apply + (Ty.path "core::option::Option") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ] + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + "iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "accounts" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let address := M.copy (| ฮณ0_0 |) in + let account := M.copy (| ฮณ0_1 |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm::db::states::plain_account::PlainAccount" + ] + ], + "map", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm::db::states::plain_account::PlainAccount" + ] + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm::db::states::plain_account::PlainAccount" + ] + ] + ] + (Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm::db::states::plain_account::PlainAccount" + ] + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::plain_account::PlainAccount" + ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let plain_acc := M.copy (| ฮณ |) in + Value.Tuple + [ + M.read (| M.read (| address |) |); + M.read (| plain_acc |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_trie_account : + M.IsAssociatedFunction Self "trie_account" trie_account. + + (* + pub fn insert_not_existing(&mut self, address: Address) { + self.accounts + .insert(address, CacheAccount::new_loaded_not_existing()); + } + *) + Definition insert_not_existing (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "accounts" + |); + M.read (| address |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "new_loaded_not_existing", + [] + |), + [] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_not_existing : + M.IsAssociatedFunction Self "insert_not_existing" insert_not_existing. + + (* + pub fn insert_account(&mut self, address: Address, info: AccountInfo) { + let account = if !info.is_empty() { + CacheAccount::new_loaded(info, HashMap::default()) + } else { + CacheAccount::new_loaded_empty_eip161(HashMap::default()) + }; + self.accounts.insert(address, account); + } + *) + Definition insert_account (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; info ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let info := M.alloc (| info |) in + M.read (| + let~ account := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "is_empty", + [] + |), + [ info ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "new_loaded", + [] + |), + [ + M.read (| info |); + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "new_loaded_empty_eip161", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |) + ] + |) + |))) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "accounts" + |); + M.read (| address |); + M.read (| account |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_account : + M.IsAssociatedFunction Self "insert_account" insert_account. + + (* + pub fn insert_account_with_storage( + &mut self, + address: Address, + info: AccountInfo, + storage: PlainStorage, + ) { + let account = if !info.is_empty() { + CacheAccount::new_loaded(info, storage) + } else { + CacheAccount::new_loaded_empty_eip161(storage) + }; + self.accounts.insert(address, account); + } + *) + Definition insert_account_with_storage (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; info; storage ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let info := M.alloc (| info |) in + let storage := M.alloc (| storage |) in + M.read (| + let~ account := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "is_empty", + [] + |), + [ info ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "new_loaded", + [] + |), + [ M.read (| info |); M.read (| storage |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "new_loaded_empty_eip161", + [] + |), + [ M.read (| storage |) ] + |) + |))) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "accounts" + |); + M.read (| address |); + M.read (| account |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_account_with_storage : + M.IsAssociatedFunction Self "insert_account_with_storage" insert_account_with_storage. + + (* + pub fn apply_evm_state(&mut self, evm_state: EVMState) -> Vec<(Address, TransitionAccount)> { + let mut transitions = Vec::with_capacity(evm_state.len()); + for (address, account) in evm_state { + if let Some(transition) = self.apply_account_state(address, account) { + transitions.push((address, transition)); + } + } + transitions + } + *) + Definition apply_evm_state (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; evm_state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let evm_state := M.alloc (| evm_state |) in + M.read (| + let~ transitions := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount" + ]; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ evm_state ] + |) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ M.read (| evm_state |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let address := M.copy (| ฮณ1_0 |) in + let account := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::cache::CacheState", + "apply_account_state", + [] + |), + [ + M.read (| self |); + M.read (| address |); + M.read (| account |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let transition := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + transitions; + Value.Tuple + [ + M.read (| address |); + M.read (| transition |) + ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + transitions + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_apply_evm_state : + M.IsAssociatedFunction Self "apply_evm_state" apply_evm_state. + + (* + fn apply_account_state( + &mut self, + address: Address, + account: Account, + ) -> Option { + // not touched account are never changed. + if !account.is_touched() { + return None; + } + + let this_account = self + .accounts + .get_mut(&address) + .expect("All accounts should be present inside cache"); + + // If it is marked as selfdestructed inside revm + // we need to changed state to destroyed. + if account.is_selfdestructed() { + return this_account.selfdestruct(); + } + + // Note: it can happen that created contract get selfdestructed in same block + // that is why is_created is checked after selfdestructed + // + // Note: Create2 opcode (Petersburg) was after state clear EIP (Spurious Dragon) + // + // Note: It is possibility to create KECCAK_EMPTY contract with some storage + // by just setting storage inside CRATE constructor. Overlap of those contracts + // is not possible because CREATE2 is introduced later. + if account.is_created() { + return Some(this_account.newly_created(account.info, account.storage)); + } + + // Account is touched, but not selfdestructed or newly created. + // Account can be touched and not changed. + // And when empty account is touched it needs to be removed from database. + // EIP-161 state clear + if account.is_empty() { + if self.has_state_clear { + // touch empty account. + this_account.touch_empty_eip161() + } else { + // if account is empty and state clear is not enabled we should save + // empty account. + this_account.touch_create_pre_eip161(account.storage) + } + } else { + Some(this_account.change(account.info, account.storage)) + } + } + *) + Definition apply_account_state (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; account ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let account := M.alloc (| account |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_touched", + [] + |), + [ account ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ this_account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm::db::states::cache_account::CacheAccount" ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "accounts" + |); + address + ] + |); + M.read (| Value.String "All accounts should be present inside cache" |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_selfdestructed", + [] + |), + [ account ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "selfdestruct", + [] + |), + [ M.read (| this_account |) ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_created", + [] + |), + [ account ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::cache_account::CacheAccount", + "newly_created", + [] + |), + [ + M.read (| this_account |); + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm_primitives::state::Account", + "info" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm_primitives::state::Account", + "storage" + |) + |) + ] + |) + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_empty", + [] + |), + [ account ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache::CacheState", + "has_state_clear" + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "touch_empty_eip161", + [] + |), + [ M.read (| this_account |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "touch_create_pre_eip161", + [] + |), + [ + M.read (| this_account |); + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm_primitives::state::Account", + "storage" + |) + |) + ] + |) + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "change", + [] + |), + [ + M.read (| this_account |); + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm_primitives::state::Account", + "info" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm_primitives::state::Account", + "storage" + |) + |) + ] + |) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_apply_account_state : + M.IsAssociatedFunction Self "apply_account_state" apply_account_state. + End Impl_revm_db_states_cache_CacheState. + End cache. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/cache_account.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/cache_account.md new file mode 100644 index 00000000..2cee721b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/cache_account.md @@ -0,0 +1,3285 @@ +# ๐Ÿ“ cache_account.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/cache_account.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module cache_account. + (* StructRecord + { + name := "CacheAccount"; + ty_params := []; + fields := + [ + ("account", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ]); + ("status", Ty.path "revm::db::states::account_status::AccountStatus") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_cache_account_CacheAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::cache_account::CacheAccount". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::cache_account::CacheAccount" + [ + ("account", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |)); + ("status", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::db::states::account_status::AccountStatus", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_cache_account_CacheAccount. + + Module Impl_core_fmt_Debug_for_revm_db_states_cache_account_CacheAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::cache_account::CacheAccount". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CacheAccount" |); + M.read (| Value.String "account" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |)); + M.read (| Value.String "status" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_cache_account_CacheAccount. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_cache_account_CacheAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::cache_account::CacheAccount". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_cache_account_CacheAccount. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_cache_account_CacheAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::cache_account::CacheAccount". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::account_status::AccountStatus", + [ Ty.path "revm::db::states::account_status::AccountStatus" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_cache_account_CacheAccount. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_cache_account_CacheAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::cache_account::CacheAccount". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_cache_account_CacheAccount. + + Module Impl_core_cmp_Eq_for_revm_db_states_cache_account_CacheAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::cache_account::CacheAccount". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_cache_account_CacheAccount. + + Module Impl_core_convert_From_revm_db_states_bundle_account_BundleAccount_for_revm_db_states_cache_account_CacheAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::cache_account::CacheAccount". + + (* + fn from(account: BundleAccount) -> Self { + let storage = account + .storage + .iter() + .map(|(k, v)| ( *k, v.present_value)) + .collect(); + let plain_account = account + .account_info() + .map(|info| PlainAccount { info, storage }); + Self { + account: plain_account, + status: account.status, + } + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ account ] => + ltac:(M.monadic + (let account := M.alloc (| account |) in + M.read (| + let~ storage := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "map", + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "iter", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + account, + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let k := M.copy (| ฮณ0_0 |) in + let v := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| M.read (| k |) |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| v |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ plain_account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "map", + [ + Ty.path "revm::db::states::plain_account::PlainAccount"; + Ty.function + [ Ty.tuple [ Ty.path "revm_primitives::state::AccountInfo" ] ] + (Ty.path "revm::db::states::plain_account::PlainAccount") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_account::BundleAccount", + "account_info", + [] + |), + [ account ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ + ("info", M.read (| info |)); + ("storage", M.read (| storage |)) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::db::states::cache_account::CacheAccount" + [ + ("account", M.read (| plain_account |)); + ("status", + M.read (| + M.SubPointer.get_struct_record_field (| + account, + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + |)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) + [ (* T *) Ty.path "revm::db::states::bundle_account::BundleAccount" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_db_states_bundle_account_BundleAccount_for_revm_db_states_cache_account_CacheAccount. + + Module Impl_revm_db_states_cache_account_CacheAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::cache_account::CacheAccount". + + (* + pub fn new_loaded(info: AccountInfo, storage: PlainStorage) -> Self { + Self { + account: Some(PlainAccount { info, storage }), + status: AccountStatus::Loaded, + } + } + *) + Definition new_loaded (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ info; storage ] => + ltac:(M.monadic + (let info := M.alloc (| info |) in + let storage := M.alloc (| storage |) in + Value.StructRecord + "revm::db::states::cache_account::CacheAccount" + [ + ("account", + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ ("info", M.read (| info |)); ("storage", M.read (| storage |)) ] + ]); + ("status", + Value.StructTuple "revm::db::states::account_status::AccountStatus::Loaded" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_loaded : M.IsAssociatedFunction Self "new_loaded" new_loaded. + + (* + pub fn new_loaded_empty_eip161(storage: PlainStorage) -> Self { + Self { + account: Some(PlainAccount::new_empty_with_storage(storage)), + status: AccountStatus::LoadedEmptyEIP161, + } + } + *) + Definition new_loaded_empty_eip161 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ storage ] => + ltac:(M.monadic + (let storage := M.alloc (| storage |) in + Value.StructRecord + "revm::db::states::cache_account::CacheAccount" + [ + ("account", + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::plain_account::PlainAccount", + "new_empty_with_storage", + [] + |), + [ M.read (| storage |) ] + |) + ]); + ("status", + Value.StructTuple + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_loaded_empty_eip161 : + M.IsAssociatedFunction Self "new_loaded_empty_eip161" new_loaded_empty_eip161. + + (* + pub fn new_loaded_not_existing() -> Self { + Self { + account: None, + status: AccountStatus::LoadedNotExisting, + } + } + *) + Definition new_loaded_not_existing (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::cache_account::CacheAccount" + [ + ("account", Value.StructTuple "core::option::Option::None" []); + ("status", + Value.StructTuple + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_loaded_not_existing : + M.IsAssociatedFunction Self "new_loaded_not_existing" new_loaded_not_existing. + + (* + pub fn new_newly_created(info: AccountInfo, storage: PlainStorage) -> Self { + Self { + account: Some(PlainAccount { info, storage }), + status: AccountStatus::InMemoryChange, + } + } + *) + Definition new_newly_created (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ info; storage ] => + ltac:(M.monadic + (let info := M.alloc (| info |) in + let storage := M.alloc (| storage |) in + Value.StructRecord + "revm::db::states::cache_account::CacheAccount" + [ + ("account", + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ ("info", M.read (| info |)); ("storage", M.read (| storage |)) ] + ]); + ("status", + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_newly_created : + M.IsAssociatedFunction Self "new_newly_created" new_newly_created. + + (* + pub fn new_destroyed() -> Self { + Self { + account: None, + status: AccountStatus::Destroyed, + } + } + *) + Definition new_destroyed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::cache_account::CacheAccount" + [ + ("account", Value.StructTuple "core::option::Option::None" []); + ("status", + Value.StructTuple + "revm::db::states::account_status::AccountStatus::Destroyed" + []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_destroyed : + M.IsAssociatedFunction Self "new_destroyed" new_destroyed. + + (* + pub fn new_changed(info: AccountInfo, storage: PlainStorage) -> Self { + Self { + account: Some(PlainAccount { info, storage }), + status: AccountStatus::Changed, + } + } + *) + Definition new_changed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ info; storage ] => + ltac:(M.monadic + (let info := M.alloc (| info |) in + let storage := M.alloc (| storage |) in + Value.StructRecord + "revm::db::states::cache_account::CacheAccount" + [ + ("account", + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ ("info", M.read (| info |)); ("storage", M.read (| storage |)) ] + ]); + ("status", + Value.StructTuple "revm::db::states::account_status::AccountStatus::Changed" []) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_changed : + M.IsAssociatedFunction Self "new_changed" new_changed. + + (* + pub fn is_some(&self) -> bool { + matches!( + self.status, + AccountStatus::Changed + | AccountStatus::InMemoryChange + | AccountStatus::DestroyedChanged + | AccountStatus::Loaded + | AccountStatus::LoadedEmptyEIP161 + ) + } + *) + Definition is_some (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedChanged" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_some : M.IsAssociatedFunction Self "is_some" is_some. + + (* + pub fn storage_slot(&self, slot: U256) -> Option { + self.account + .as_ref() + .and_then(|a| a.storage.get(&slot).cloned()) + } + *) + Definition storage_slot (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; slot ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let slot := M.alloc (| slot |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ], + "and_then", + [ + Ty.path "ruint::Uint"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ] + ] + (Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ] ], + "cloned", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "ruint::Uint" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm::db::states::plain_account::PlainAccount", + "storage" + |); + slot + ] + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_storage_slot : + M.IsAssociatedFunction Self "storage_slot" storage_slot. + + (* + pub fn account_info(&self) -> Option { + self.account.as_ref().map(|a| a.info.clone()) + } + *) + Definition account_info (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ], + "map", + [ + Ty.path "revm_primitives::state::AccountInfo"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ] + ] + (Ty.path "revm_primitives::state::AccountInfo") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountInfo", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm::db::states::plain_account::PlainAccount", + "info" + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_account_info : + M.IsAssociatedFunction Self "account_info" account_info. + + (* + pub fn into_components(self) -> (Option<(AccountInfo, PlainStorage)>, AccountStatus) { + (self.account.map(|a| a.into_components()), self.status) + } + *) + Definition into_components (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "map", + [ + Ty.tuple + [ + Ty.path "revm_primitives::state::AccountInfo"; + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ]; + Ty.function + [ Ty.tuple [ Ty.path "revm::db::states::plain_account::PlainAccount" ] ] + (Ty.tuple + [ + Ty.path "revm_primitives::state::AccountInfo"; + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ]) + ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::cache_account::CacheAccount", + "account" + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::plain_account::PlainAccount", + "into_components", + [] + |), + [ M.read (| a |) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_components : + M.IsAssociatedFunction Self "into_components" into_components. + + (* + pub fn touch_create_pre_eip161( + &mut self, + storage: StorageWithOriginalValues, + ) -> Option { + let previous_status = self.status; + + let had_no_info = self + .account + .as_ref() + .map(|a| a.info.is_empty()) + .unwrap_or_default(); + self.status = self.status.on_touched_created_pre_eip161(had_no_info)?; + + let plain_storage = storage.iter().map(|(k, v)| ( *k, v.present_value)).collect(); + let previous_info = self.account.take().map(|a| a.info); + + self.account = Some(PlainAccount::new_empty_with_storage(plain_storage)); + + Some(TransitionAccount { + info: Some(AccountInfo::default()), + status: self.status, + previous_info, + previous_status, + storage, + storage_was_destroyed: false, + }) + } + *) + Definition touch_create_pre_eip161 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; storage ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let storage := M.alloc (| storage |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ previous_status := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |) in + let~ had_no_info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "bool" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ], + "map", + [ + Ty.path "bool"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm::db::states::plain_account::PlainAccount" + ] + ] + ] + (Ty.path "bool") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm::db::states::plain_account::PlainAccount", + "info" + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |), + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::account_status::AccountStatus" ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "on_touched_created_pre_eip161", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |); + M.read (| had_no_info |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "core::convert::Infallible" ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + |) in + let~ plain_storage := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "map", + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "iter", + [] + |), + [ storage ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let k := M.copy (| ฮณ0_0 |) in + let v := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| M.read (| k |) |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| v |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ previous_info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "map", + [ + Ty.path "revm_primitives::state::AccountInfo"; + Ty.function + [ + Ty.tuple + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ] + (Ty.path "revm_primitives::state::AccountInfo") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "take", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + a, + "revm::db::states::plain_account::PlainAccount", + "info" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |), + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::plain_account::PlainAccount", + "new_empty_with_storage", + [] + |), + [ M.read (| plain_storage |) ] + |) + ] + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::transition_account::TransitionAccount" + [ + ("info", + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::AccountInfo", + [], + "default", + [] + |), + [] + |) + ]); + ("status", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |)); + ("previous_info", M.read (| previous_info |)); + ("previous_status", M.read (| previous_status |)); + ("storage", M.read (| storage |)); + ("storage_was_destroyed", Value.Bool false) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_touch_create_pre_eip161 : + M.IsAssociatedFunction Self "touch_create_pre_eip161" touch_create_pre_eip161. + + (* + pub fn touch_empty_eip161(&mut self) -> Option { + let previous_status = self.status; + + // Set account to None. + let previous_info = self.account.take().map(|acc| acc.info); + + // Set account state to Destroyed as we need to clear the storage if it exist. + self.status = self.status.on_touched_empty_post_eip161(); + + if matches!( + previous_status, + AccountStatus::LoadedNotExisting + | AccountStatus::Destroyed + | AccountStatus::DestroyedAgain + ) { + None + } else { + Some(TransitionAccount { + info: None, + status: self.status, + previous_info, + previous_status, + storage: HashMap::default(), + storage_was_destroyed: true, + }) + } + } + *) + Definition touch_empty_eip161 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ previous_status := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |) in + let~ previous_info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "map", + [ + Ty.path "revm_primitives::state::AccountInfo"; + Ty.function + [ Ty.tuple [ Ty.path "revm::db::states::plain_account::PlainAccount" ] ] + (Ty.path "revm_primitives::state::AccountInfo") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "take", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let acc := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + acc, + "revm::db::states::plain_account::PlainAccount", + "info" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "on_touched_empty_post_eip161", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.match_operator (| + previous_status, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::transition_account::TransitionAccount" + [ + ("info", Value.StructTuple "core::option::Option::None" []); + ("status", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |)); + ("previous_info", M.read (| previous_info |)); + ("previous_status", M.read (| previous_status |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("storage_was_destroyed", Value.Bool true) + ] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_touch_empty_eip161 : + M.IsAssociatedFunction Self "touch_empty_eip161" touch_empty_eip161. + + (* + pub fn selfdestruct(&mut self) -> Option { + // account should be None after selfdestruct so we can take it. + let previous_info = self.account.take().map(|a| a.info); + let previous_status = self.status; + + self.status = self.status.on_selfdestructed(); + + if previous_status == AccountStatus::LoadedNotExisting { + None + } else { + Some(TransitionAccount { + info: None, + status: self.status, + previous_info, + previous_status, + storage: HashMap::new(), + storage_was_destroyed: true, + }) + } + } + *) + Definition selfdestruct (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ previous_info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "map", + [ + Ty.path "revm_primitives::state::AccountInfo"; + Ty.function + [ Ty.tuple [ Ty.path "revm::db::states::plain_account::PlainAccount" ] ] + (Ty.path "revm_primitives::state::AccountInfo") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "take", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + a, + "revm::db::states::plain_account::PlainAccount", + "info" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ previous_status := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "on_selfdestructed", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::account_status::AccountStatus", + [ Ty.path "revm::db::states::account_status::AccountStatus" ], + "eq", + [] + |), + [ + previous_status; + M.alloc (| + Value.StructTuple + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::transition_account::TransitionAccount" + [ + ("info", Value.StructTuple "core::option::Option::None" []); + ("status", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |)); + ("previous_info", M.read (| previous_info |)); + ("previous_status", M.read (| previous_status |)); + ("storage", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("storage_was_destroyed", Value.Bool true) + ] + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_selfdestruct : + M.IsAssociatedFunction Self "selfdestruct" selfdestruct. + + (* + pub fn newly_created( + &mut self, + new_info: AccountInfo, + new_storage: StorageWithOriginalValues, + ) -> TransitionAccount { + let previous_status = self.status; + let previous_info = self.account.take().map(|a| a.info); + + let new_bundle_storage = new_storage + .iter() + .map(|(k, s)| ( *k, s.present_value)) + .collect(); + + self.status = self.status.on_created(); + let transition_account = TransitionAccount { + info: Some(new_info.clone()), + status: self.status, + previous_status, + previous_info, + storage: new_storage, + storage_was_destroyed: false, + }; + self.account = Some(PlainAccount { + info: new_info, + storage: new_bundle_storage, + }); + transition_account + } + *) + Definition newly_created (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; new_info; new_storage ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let new_info := M.alloc (| new_info |) in + let new_storage := M.alloc (| new_storage |) in + M.read (| + let~ previous_status := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |) in + let~ previous_info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "map", + [ + Ty.path "revm_primitives::state::AccountInfo"; + Ty.function + [ Ty.tuple [ Ty.path "revm::db::states::plain_account::PlainAccount" ] ] + (Ty.path "revm_primitives::state::AccountInfo") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "take", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + a, + "revm::db::states::plain_account::PlainAccount", + "info" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ new_bundle_storage := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "map", + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "iter", + [] + |), + [ new_storage ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let k := M.copy (| ฮณ0_0 |) in + let s := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| M.read (| k |) |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| s |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "on_created", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + ] + |) + |) in + let~ transition_account := + M.alloc (| + Value.StructRecord + "revm::db::states::transition_account::TransitionAccount" + [ + ("info", + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountInfo", + [], + "clone", + [] + |), + [ new_info ] + |) + ]); + ("status", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |)); + ("previous_status", M.read (| previous_status |)); + ("previous_info", M.read (| previous_info |)); + ("storage", M.read (| new_storage |)); + ("storage_was_destroyed", Value.Bool false) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |), + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ + ("info", M.read (| new_info |)); + ("storage", M.read (| new_bundle_storage |)) + ] + ] + |) in + transition_account + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_newly_created : + M.IsAssociatedFunction Self "newly_created" newly_created. + + (* + pub fn increment_balance(&mut self, balance: u128) -> Option { + if balance == 0 { + return None; + } + let (_, transition) = self.account_info_change(|info| { + info.balance = info.balance.saturating_add(U256::from(balance)); + }); + Some(transition) + } + *) + Definition increment_balance (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; balance ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let balance := M.alloc (| balance |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq (M.read (| balance |)) (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple "core::option::Option::None" [] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "account_info_change", + [ + Ty.tuple []; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.read (| self |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| info |), + "revm_primitives::state::AccountInfo", + "balance" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "saturating_add", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| info |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u128" ] + |), + [ M.read (| balance |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let transition := M.copy (| ฮณ0_1 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ M.read (| transition |) ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_increment_balance : + M.IsAssociatedFunction Self "increment_balance" increment_balance. + + (* + fn account_info_change T>( + &mut self, + change: F, + ) -> (T, TransitionAccount) { + let previous_status = self.status; + let previous_info = self.account_info(); + let mut account = self.account.take().unwrap_or_default(); + let output = change(&mut account.info); + self.account = Some(account); + + let had_no_nonce_and_code = previous_info + .as_ref() + .map(AccountInfo::has_no_code_and_nonce) + .unwrap_or_default(); + self.status = self.status.on_changed(had_no_nonce_and_code); + + ( + output, + TransitionAccount { + info: self.account_info(), + status: self.status, + previous_info, + previous_status, + storage: HashMap::new(), + storage_was_destroyed: false, + }, + ) + } + *) + Definition account_info_change (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ T; F ], [ self; change ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let change := M.alloc (| change |) in + M.read (| + let~ previous_status := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |) in + let~ previous_info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "account_info", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "take", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |) + ] + |) + |) in + let~ output := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnOnce", + F, + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + ], + "call_once", + [] + |), + [ + M.read (| change |); + Value.Tuple + [ + M.SubPointer.get_struct_record_field (| + account, + "revm::db::states::plain_account::PlainAccount", + "info" + |) + ] + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |), + Value.StructTuple "core::option::Option::Some" [ M.read (| account |) ] + |) in + let~ had_no_nonce_and_code := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "bool" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "map", + [ + Ty.path "bool"; + Ty.function + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + (Ty.path "bool") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "as_ref", + [] + |), + [ previous_info ] + |); + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "has_no_code_and_nonce", + [] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "on_changed", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |); + M.read (| had_no_nonce_and_code |) + ] + |) + |) in + M.alloc (| + Value.Tuple + [ + M.read (| output |); + Value.StructRecord + "revm::db::states::transition_account::TransitionAccount" + [ + ("info", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "account_info", + [] + |), + [ M.read (| self |) ] + |)); + ("status", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |)); + ("previous_info", M.read (| previous_info |)); + ("previous_status", M.read (| previous_status |)); + ("storage", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("storage_was_destroyed", Value.Bool false) + ] + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_account_info_change : + M.IsAssociatedFunction Self "account_info_change" account_info_change. + + (* + pub fn drain_balance(&mut self) -> (u128, TransitionAccount) { + self.account_info_change(|info| { + let output = info.balance; + info.balance = U256::ZERO; + output.try_into().unwrap() + }) + } + *) + Definition drain_balance (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "account_info_change", + [ + Ty.path "u128"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + ] + (Ty.path "u128") + ] + |), + [ + M.read (| self |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + M.read (| + let~ output := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| info |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| info |), + "revm_primitives::state::AccountInfo", + "balance" + |), + M.read (| M.get_constant (| "ruint::ZERO" |) |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u128"; + Ty.apply + (Ty.path "ruint::from::FromUintError") + [ Ty.path "u128" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.path "ruint::Uint", + [ Ty.path "u128" ], + "try_into", + [] + |), + [ M.read (| output |) ] + |) + ] + |) + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_drain_balance : + M.IsAssociatedFunction Self "drain_balance" drain_balance. + + (* + pub fn change( + &mut self, + new: AccountInfo, + storage: StorageWithOriginalValues, + ) -> TransitionAccount { + let previous_status = self.status; + let previous_info = self.account.as_ref().map(|a| a.info.clone()); + let mut this_storage = self + .account + .take() + .map(|acc| acc.storage) + .unwrap_or_default(); + + this_storage.extend(storage.iter().map(|(k, s)| ( *k, s.present_value))); + let changed_account = PlainAccount { + info: new, + storage: this_storage, + }; + + let had_no_nonce_and_code = previous_info + .as_ref() + .map(AccountInfo::has_no_code_and_nonce) + .unwrap_or_default(); + self.status = self.status.on_changed(had_no_nonce_and_code); + self.account = Some(changed_account); + + TransitionAccount { + info: self.account.as_ref().map(|a| a.info.clone()), + status: self.status, + previous_info, + previous_status, + storage, + storage_was_destroyed: false, + } + } + *) + Definition change (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; new; storage ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let new := M.alloc (| new |) in + let storage := M.alloc (| storage |) in + M.read (| + let~ previous_status := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |) in + let~ previous_info := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ], + "map", + [ + Ty.path "revm_primitives::state::AccountInfo"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ] + ] + (Ty.path "revm_primitives::state::AccountInfo") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountInfo", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm::db::states::plain_account::PlainAccount", + "info" + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ this_storage := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "map", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ]; + Ty.function + [ + Ty.tuple + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ] + (Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "take", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let acc := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + acc, + "revm::db::states::plain_account::PlainAccount", + "storage" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::Extend", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [ Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ] ], + "extend", + [ + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]) + ] + ] + |), + [ + this_storage; + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Iter") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "map", + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "iter", + [] + |), + [ storage ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let k := M.copy (| ฮณ0_0 |) in + let s := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| M.read (| k |) |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| s |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ changed_account := + M.alloc (| + Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ ("info", M.read (| new |)); ("storage", M.read (| this_storage |)) ] + |) in + let~ had_no_nonce_and_code := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "bool" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "map", + [ + Ty.path "bool"; + Ty.function + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + (Ty.path "bool") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "as_ref", + [] + |), + [ previous_info ] + |); + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "has_no_code_and_nonce", + [] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "on_changed", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |); + M.read (| had_no_nonce_and_code |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |), + Value.StructTuple "core::option::Option::Some" [ M.read (| changed_account |) ] + |) in + M.alloc (| + Value.StructRecord + "revm::db::states::transition_account::TransitionAccount" + [ + ("info", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ], + "map", + [ + Ty.path "revm_primitives::state::AccountInfo"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ] + ] + ] + (Ty.path "revm_primitives::state::AccountInfo") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::plain_account::PlainAccount" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountInfo", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| a |), + "revm::db::states::plain_account::PlainAccount", + "info" + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)); + ("status", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + |)); + ("previous_info", M.read (| previous_info |)); + ("previous_status", M.read (| previous_status |)); + ("storage", M.read (| storage |)); + ("storage_was_destroyed", Value.Bool false) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_change : M.IsAssociatedFunction Self "change" change. + End Impl_revm_db_states_cache_account_CacheAccount. + End cache_account. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/changes.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/changes.md new file mode 100644 index 00000000..353add72 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/changes.md @@ -0,0 +1,1405 @@ +# ๐Ÿ“ changes.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/changes.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module changes. + (* StructRecord + { + name := "StateChangeset"; + ty_params := []; + fields := + [ + ("accounts", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "alloc::alloc::Global" + ]); + ("storage", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::db::states::changes::PlainStorageChangeset"; + Ty.path "alloc::alloc::Global" + ]); + ("contracts", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_changes_StateChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::StateChangeset". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::changes::StateChangeset" + [ + ("accounts", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::StateChangeset", + "accounts" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::db::states::changes::PlainStorageChangeset"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::StateChangeset", + "storage" + |) + ] + |)); + ("contracts", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::StateChangeset", + "contracts" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_changes_StateChangeset. + + Module Impl_core_fmt_Debug_for_revm_db_states_changes_StateChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::StateChangeset". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "StateChangeset" |); + M.read (| Value.String "accounts" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::StateChangeset", + "accounts" + |)); + M.read (| Value.String "storage" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::StateChangeset", + "storage" + |)); + M.read (| Value.String "contracts" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::StateChangeset", + "contracts" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_changes_StateChangeset. + + Module Impl_core_default_Default_for_revm_db_states_changes_StateChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::StateChangeset". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::changes::StateChangeset" + [ + ("accounts", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::db::states::changes::PlainStorageChangeset"; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)); + ("contracts", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_changes_StateChangeset. + + (* StructRecord + { + name := "PlainStorageChangeset"; + ty_params := []; + fields := + [ + ("address", Ty.path "alloy_primitives::bits::address::Address"); + ("wipe_storage", Ty.path "bool"); + ("storage", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_changes_PlainStorageChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageChangeset". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::changes::PlainStorageChangeset" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageChangeset", + "address" + |) + ] + |)); + ("wipe_storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageChangeset", + "wipe_storage" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageChangeset", + "storage" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_changes_PlainStorageChangeset. + + Module Impl_core_fmt_Debug_for_revm_db_states_changes_PlainStorageChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageChangeset". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "PlainStorageChangeset" |); + M.read (| Value.String "address" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageChangeset", + "address" + |)); + M.read (| Value.String "wipe_storage" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageChangeset", + "wipe_storage" + |)); + M.read (| Value.String "storage" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageChangeset", + "storage" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_changes_PlainStorageChangeset. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_changes_PlainStorageChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageChangeset". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_changes_PlainStorageChangeset. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_changes_PlainStorageChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageChangeset". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageChangeset", + "address" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::changes::PlainStorageChangeset", + "address" + |) + ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageChangeset", + "wipe_storage" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::changes::PlainStorageChangeset", + "wipe_storage" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageChangeset", + "storage" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::changes::PlainStorageChangeset", + "storage" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_changes_PlainStorageChangeset. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_changes_PlainStorageChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageChangeset". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_changes_PlainStorageChangeset. + + Module Impl_core_cmp_Eq_for_revm_db_states_changes_PlainStorageChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageChangeset". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_changes_PlainStorageChangeset. + + Module Impl_core_default_Default_for_revm_db_states_changes_PlainStorageChangeset. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageChangeset". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::changes::PlainStorageChangeset" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bits::address::Address", + [], + "default", + [] + |), + [] + |)); + ("wipe_storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_changes_PlainStorageChangeset. + + (* StructRecord + { + name := "PlainStorageRevert"; + ty_params := []; + fields := + [ + ("address", Ty.path "alloy_primitives::bits::address::Address"); + ("wiped", Ty.path "bool"); + ("storage_revert", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ Ty.path "ruint::Uint"; Ty.path "revm::db::states::reverts::RevertToSlot" ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_changes_PlainStorageRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageRevert". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::changes::PlainStorageRevert" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageRevert", + "address" + |) + ] + |)); + ("wiped", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageRevert", + "wiped" + |) + ] + |)); + ("storage_revert", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageRevert", + "storage_revert" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_changes_PlainStorageRevert. + + Module Impl_core_fmt_Debug_for_revm_db_states_changes_PlainStorageRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageRevert". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "PlainStorageRevert" |); + M.read (| Value.String "address" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageRevert", + "address" + |)); + M.read (| Value.String "wiped" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageRevert", + "wiped" + |)); + M.read (| Value.String "storage_revert" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageRevert", + "storage_revert" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_changes_PlainStorageRevert. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_changes_PlainStorageRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageRevert". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_changes_PlainStorageRevert. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_changes_PlainStorageRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageRevert". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageRevert", + "address" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::changes::PlainStorageRevert", + "address" + |) + ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageRevert", + "wiped" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::changes::PlainStorageRevert", + "wiped" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStorageRevert", + "storage_revert" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::changes::PlainStorageRevert", + "storage_revert" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_changes_PlainStorageRevert. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_changes_PlainStorageRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageRevert". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_changes_PlainStorageRevert. + + Module Impl_core_cmp_Eq_for_revm_db_states_changes_PlainStorageRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageRevert". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_changes_PlainStorageRevert. + + Module Impl_core_default_Default_for_revm_db_states_changes_PlainStorageRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStorageRevert". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::changes::PlainStorageRevert" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "alloy_primitives::bits::address::Address", + [], + "default", + [] + |), + [] + |)); + ("wiped", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)); + ("storage_revert", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_changes_PlainStorageRevert. + + (* StructRecord + { + name := "PlainStateReverts"; + ty_params := []; + fields := + [ + ("accounts", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ]); + ("storage", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::db::states::changes::PlainStorageRevert"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_changes_PlainStateReverts. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStateReverts". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::changes::PlainStateReverts" + [ + ("accounts", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStateReverts", + "accounts" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::db::states::changes::PlainStorageRevert"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStateReverts", + "storage" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_changes_PlainStateReverts. + + Module Impl_core_fmt_Debug_for_revm_db_states_changes_PlainStateReverts. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStateReverts". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "PlainStateReverts" |); + M.read (| Value.String "accounts" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStateReverts", + "accounts" + |)); + M.read (| Value.String "storage" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::changes::PlainStateReverts", + "storage" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_changes_PlainStateReverts. + + Module Impl_core_default_Default_for_revm_db_states_changes_PlainStateReverts. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStateReverts". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::changes::PlainStateReverts" + [ + ("accounts", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::db::states::changes::PlainStorageRevert"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_changes_PlainStateReverts. + + Module Impl_revm_db_states_changes_PlainStateReverts. + Definition Self : Ty.t := Ty.path "revm::db::states::changes::PlainStateReverts". + + (* + pub fn with_capacity(capacity: usize) -> Self { + Self { + accounts: Vec::with_capacity(capacity), + storage: Vec::with_capacity(capacity), + } + } + *) + Definition with_capacity (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ capacity ] => + ltac:(M.monadic + (let capacity := M.alloc (| capacity |) in + Value.StructRecord + "revm::db::states::changes::PlainStateReverts" + [ + ("accounts", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ M.read (| capacity |) ] + |)); + ("storage", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::db::states::changes::PlainStorageRevert"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ M.read (| capacity |) ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_capacity : + M.IsAssociatedFunction Self "with_capacity" with_capacity. + End Impl_revm_db_states_changes_PlainStateReverts. + + Axiom StorageRevert : + (Ty.path "revm::db::states::changes::StorageRevert") = + (Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "bool"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ]). + End changes. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/plain_account.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/plain_account.md new file mode 100644 index 00000000..ec102e47 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/plain_account.md @@ -0,0 +1,469 @@ +# ๐Ÿ“ plain_account.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/plain_account.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module plain_account. + (* StructRecord + { + name := "PlainAccount"; + ty_params := []; + fields := + [ + ("info", Ty.path "revm_primitives::state::AccountInfo"); + ("storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_plain_account_PlainAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::plain_account::PlainAccount". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountInfo", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::plain_account::PlainAccount", + "info" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::plain_account::PlainAccount", + "storage" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_plain_account_PlainAccount. + + Module Impl_core_fmt_Debug_for_revm_db_states_plain_account_PlainAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::plain_account::PlainAccount". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "PlainAccount" |); + M.read (| Value.String "info" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::plain_account::PlainAccount", + "info" + |)); + M.read (| Value.String "storage" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::plain_account::PlainAccount", + "storage" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_plain_account_PlainAccount. + + Module Impl_core_default_Default_for_revm_db_states_plain_account_PlainAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::plain_account::PlainAccount". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::AccountInfo", + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_plain_account_PlainAccount. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_plain_account_PlainAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::plain_account::PlainAccount". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_plain_account_PlainAccount. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_plain_account_PlainAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::plain_account::PlainAccount". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::state::AccountInfo", + [ Ty.path "revm_primitives::state::AccountInfo" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::plain_account::PlainAccount", + "info" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::plain_account::PlainAccount", + "info" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::plain_account::PlainAccount", + "storage" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::plain_account::PlainAccount", + "storage" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_plain_account_PlainAccount. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_plain_account_PlainAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::plain_account::PlainAccount". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_plain_account_PlainAccount. + + Module Impl_core_cmp_Eq_for_revm_db_states_plain_account_PlainAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::plain_account::PlainAccount". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_plain_account_PlainAccount. + + Module Impl_revm_db_states_plain_account_PlainAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::plain_account::PlainAccount". + + (* + pub fn new_empty_with_storage(storage: PlainStorage) -> Self { + Self { + info: AccountInfo::default(), + storage, + } + } + *) + Definition new_empty_with_storage (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ storage ] => + ltac:(M.monadic + (let storage := M.alloc (| storage |) in + Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::AccountInfo", + [], + "default", + [] + |), + [] + |)); + ("storage", M.read (| storage |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_empty_with_storage : + M.IsAssociatedFunction Self "new_empty_with_storage" new_empty_with_storage. + + (* + pub fn into_components(self) -> (AccountInfo, PlainStorage) { + (self.info, self.storage) + } + *) + Definition into_components (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::plain_account::PlainAccount", + "info" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::plain_account::PlainAccount", + "storage" + |) + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_components : + M.IsAssociatedFunction Self "into_components" into_components. + End Impl_revm_db_states_plain_account_PlainAccount. + + Axiom StorageWithOriginalValues : + (Ty.path "revm::db::states::plain_account::StorageWithOriginalValues") = + (Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ]). + + Axiom PlainStorage : + (Ty.path "revm::db::states::plain_account::PlainStorage") = + (Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ Ty.path "ruint::Uint"; Ty.path "ruint::Uint"; Ty.path "std::hash::random::RandomState" + ]). + + Module Impl_core_convert_From_revm_primitives_state_AccountInfo_for_revm_db_states_plain_account_PlainAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::plain_account::PlainAccount". + + (* + fn from(info: AccountInfo) -> Self { + Self { + info, + storage: HashMap::new(), + } + } + *) + Definition from (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ info ] => + ltac:(M.monadic + (let info := M.alloc (| info |) in + Value.StructRecord + "revm::db::states::plain_account::PlainAccount" + [ + ("info", M.read (| info |)); + ("storage", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::convert::From" + Self + (* Trait polymorphic types *) [ (* T *) Ty.path "revm_primitives::state::AccountInfo" ] + (* Instance *) [ ("from", InstanceField.Method from) ]. + End Impl_core_convert_From_revm_primitives_state_AccountInfo_for_revm_db_states_plain_account_PlainAccount. + End plain_account. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/reverts.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/reverts.md new file mode 100644 index 00000000..3ed7bfc7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/reverts.md @@ -0,0 +1,3486 @@ +# ๐Ÿ“ reverts.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/reverts.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module reverts. + (* StructTuple + { + name := "Reverts"; + ty_params := []; + fields := + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructTuple + "revm::db::states::reverts::Reverts" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::states::reverts::Reverts", + 0 + |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_reverts_Reverts. + + Module Impl_core_fmt_Debug_for_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Reverts" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::states::reverts::Reverts", + 0 + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_reverts_Reverts. + + Module Impl_core_default_Default_for_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple + "revm::db::states::reverts::Reverts" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_reverts_Reverts. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_reverts_Reverts. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::states::reverts::Reverts", + 0 + |); + M.SubPointer.get_struct_tuple_field (| + M.read (| other |), + "revm::db::states::reverts::Reverts", + 0 + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_reverts_Reverts. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_reverts_Reverts. + + Module Impl_core_cmp_Eq_for_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_reverts_Reverts. + + Module Impl_core_ops_deref_Deref_for_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + (* type Target = Vec>; *) + Definition _Target : Ty.t := + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ]. + + (* + fn deref(&self) -> &Self::Target { + &self.0 + } + *) + Definition deref (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::states::reverts::Reverts", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::Deref" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("Target", InstanceField.Ty _Target); ("deref", InstanceField.Method deref) ]. + End Impl_core_ops_deref_Deref_for_revm_db_states_reverts_Reverts. + + Module Impl_core_ops_deref_DerefMut_for_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + (* + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + *) + Definition deref_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::states::reverts::Reverts", + 0 + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::ops::deref::DerefMut" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("deref_mut", InstanceField.Method deref_mut) ]. + End Impl_core_ops_deref_DerefMut_for_revm_db_states_reverts_Reverts. + + Module Impl_revm_db_states_reverts_Reverts. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::Reverts". + + (* + pub fn new(reverts: Vec>) -> Self { + Self(reverts) + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ reverts ] => + ltac:(M.monadic + (let reverts := M.alloc (| reverts |) in + Value.StructTuple "revm::db::states::reverts::Reverts" [ M.read (| reverts |) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn sort(&mut self) { + for revert in &mut self.0 { + revert.sort_by_key(|(address, _)| *address); + } + } + *) + Definition sort (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "into_iter", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::states::reverts::Reverts", + 0 + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::IterMut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let revert := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ] + ], + "sort_by_key", + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ] + ] + ] + ] + (Ty.path + "alloy_primitives::bits::address::Address") + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ M.read (| revert |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ, + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ, + 1 + |) in + let address := M.alloc (| ฮณ1_0 |) in + M.read (| M.read (| address |) |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_sort : M.IsAssociatedFunction Self "sort" sort. + + (* + pub fn extend(&mut self, other: Reverts) { + self.0.extend(other.0); + } + *) + Definition extend (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::Extend", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "extend", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.SubPointer.get_struct_tuple_field (| + M.read (| self |), + "revm::db::states::reverts::Reverts", + 0 + |); + M.read (| + M.SubPointer.get_struct_tuple_field (| + other, + "revm::db::states::reverts::Reverts", + 0 + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_extend : M.IsAssociatedFunction Self "extend" extend. + + (* + pub fn into_plain_state_reverts(mut self) -> PlainStateReverts { + let mut state_reverts = PlainStateReverts::with_capacity(self.0.len()); + for reverts in self.0.drain(..) { + // pessimistically pre-allocate assuming _all_ accounts changed. + let mut accounts = Vec::with_capacity(reverts.len()); + let mut storage = Vec::with_capacity(reverts.len()); + for (address, revert_account) in reverts.into_iter() { + match revert_account.account { + AccountInfoRevert::RevertTo(acc) => accounts.push((address, Some(acc))), + AccountInfoRevert::DeleteIt => accounts.push((address, None)), + AccountInfoRevert::DoNothing => (), + } + if revert_account.wipe_storage || !revert_account.storage.is_empty() { + storage.push(PlainStorageRevert { + address, + wiped: revert_account.wipe_storage, + storage_revert: revert_account.storage.into_iter().collect::>(), + }); + } + } + state_reverts.accounts.push(accounts); + state_reverts.storage.push(storage); + } + state_reverts + } + *) + Definition into_plain_state_reverts (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ state_reverts := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::changes::PlainStateReverts", + "with_capacity", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_tuple_field (| + self, + "revm::db::states::reverts::Reverts", + 0 + |) + ] + |) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::drain::Drain") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "drain", + [ Ty.path "core::ops::range::RangeFull" ] + |), + [ + M.SubPointer.get_struct_tuple_field (| + self, + "revm::db::states::reverts::Reverts", + 0 + |); + Value.StructTuple "core::ops::range::RangeFull" [] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::vec::drain::Drain") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let reverts := M.copy (| ฮณ0_0 |) in + let~ accounts := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ reverts ] + |) + ] + |) + |) in + let~ storage := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm::db::states::changes::PlainStorageRevert"; + Ty.path "alloc::alloc::Global" + ], + "with_capacity", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ reverts ] + |) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| reverts |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "alloc::vec::into_iter::IntoIter") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::reverts::AccountRevert" + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.break (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 0 + |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| + ฮณ0_0, + 1 + |) in + let address := + M.copy (| ฮณ1_0 |) in + let revert_account := + M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.SubPointer.get_struct_record_field (| + revert_account, + "revm::db::states::reverts::AccountRevert", + "account" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::RevertTo", + 0 + |) in + let acc := + M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + "push", + [] + |), + [ + accounts; + Value.Tuple + [ + M.read (| + address + |); + Value.StructTuple + "core::option::Option::Some" + [ + M.read (| + acc + |) + ] + ] + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + "push", + [] + |), + [ + accounts; + Value.Tuple + [ + M.read (| + address + |); + Value.StructTuple + "core::option::Option::None" + [] + ] + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::DoNothing" + |) in + M.alloc (| + Value.Tuple [] + |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + M.read (| + M.SubPointer.get_struct_record_field (| + revert_account, + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |) + |), + ltac:(M.monadic + (UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + revert_account, + "revm::db::states::reverts::AccountRevert", + "storage" + |) + ] + |)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm::db::states::changes::PlainStorageRevert"; + Ty.path + "alloc::alloc::Global" + ], + "push", + [] + |), + [ + storage; + Value.StructRecord + "revm::db::states::changes::PlainStorageRevert" + [ + ("address", + M.read (| + address + |)); + ("wiped", + M.read (| + M.SubPointer.get_struct_record_field (| + revert_account, + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |) + |)); + ("storage_revert", + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path + "std::collections::hash::map::IntoIter") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ], + [], + "collect", + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ]; + Ty.path + "alloc::alloc::Global" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path + "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + revert_account, + "revm::db::states::reverts::AccountRevert", + "storage" + |) + |) + ] + |) + ] + |)) + ] + ] + |) + |) in + M.alloc (| + Value.Tuple [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + state_reverts, + "revm::db::states::changes::PlainStateReverts", + "accounts" + |); + M.read (| accounts |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm::db::states::changes::PlainStorageRevert"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + state_reverts, + "revm::db::states::changes::PlainStateReverts", + "storage" + |); + M.read (| storage |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + state_reverts + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_plain_state_reverts : + M.IsAssociatedFunction Self "into_plain_state_reverts" into_plain_state_reverts. + End Impl_revm_db_states_reverts_Reverts. + + (* StructRecord + { + name := "AccountRevert"; + ty_params := []; + fields := + [ + ("account", Ty.path "revm::db::states::reverts::AccountInfoRevert"); + ("storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ]); + ("previous_status", Ty.path "revm::db::states::account_status::AccountStatus"); + ("wipe_storage", Ty.path "bool") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_reverts_AccountRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountRevert". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::db::states::reverts::AccountInfoRevert", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "account" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "storage" + |) + ] + |)); + ("previous_status", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::db::states::account_status::AccountStatus", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "previous_status" + |) + ] + |)); + ("wipe_storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_reverts_AccountRevert. + + Module Impl_core_default_Default_for_revm_db_states_reverts_AccountRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountRevert". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::states::reverts::AccountInfoRevert", + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("previous_status", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::states::account_status::AccountStatus", + [], + "default", + [] + |), + [] + |)); + ("wipe_storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_reverts_AccountRevert. + + Module Impl_core_fmt_Debug_for_revm_db_states_reverts_AccountRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountRevert". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "AccountRevert" |); + M.read (| Value.String "account" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "account" + |)); + M.read (| Value.String "storage" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "storage" + |)); + M.read (| Value.String "previous_status" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "previous_status" + |)); + M.read (| Value.String "wipe_storage" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_reverts_AccountRevert. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_reverts_AccountRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountRevert". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_reverts_AccountRevert. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_reverts_AccountRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountRevert". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::reverts::AccountInfoRevert", + [ Ty.path "revm::db::states::reverts::AccountInfoRevert" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "account" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::reverts::AccountRevert", + "account" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "storage" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::reverts::AccountRevert", + "storage" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::account_status::AccountStatus", + [ Ty.path "revm::db::states::account_status::AccountStatus" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "previous_status" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::reverts::AccountRevert", + "previous_status" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_reverts_AccountRevert. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_reverts_AccountRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountRevert". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_reverts_AccountRevert. + + Module Impl_core_cmp_Eq_for_revm_db_states_reverts_AccountRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountRevert". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_reverts_AccountRevert. + + Module Impl_revm_db_states_reverts_AccountRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountRevert". + + (* + pub fn size_hint(&self) -> usize { + 1 + self.storage.len() + } + *) + Definition size_hint (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + BinOp.Wrap.add + Integer.Usize + (Value.Integer 1) + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "storage" + |) + ] + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_size_hint : M.IsAssociatedFunction Self "size_hint" size_hint. + + (* + pub fn new_selfdestructed_again( + status: AccountStatus, + account: AccountInfoRevert, + mut previous_storage: StorageWithOriginalValues, + updated_storage: StorageWithOriginalValues, + ) -> Self { + // Take present storage values as the storages that we are going to revert to. + // As those values got destroyed. + let mut previous_storage: HashMap = previous_storage + .drain() + .map(|(key, value)| (key, RevertToSlot::Some(value.present_value))) + .collect(); + for (key, _) in updated_storage { + previous_storage + .entry(key) + .or_insert(RevertToSlot::Destroyed); + } + AccountRevert { + account, + storage: previous_storage, + previous_status: status, + wipe_storage: false, + } + } + *) + Definition new_selfdestructed_again (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ status; account; previous_storage; updated_storage ] => + ltac:(M.monadic + (let status := M.alloc (| status |) in + let account := M.alloc (| account |) in + let previous_storage := M.alloc (| previous_storage |) in + let updated_storage := M.alloc (| updated_storage |) in + M.read (| + let~ previous_storage := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "std::collections::hash::map::Drain") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Drain") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "map", + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "drain", + [] + |), + [ previous_storage ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let key := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| key |); + Value.StructTuple + "revm::db::states::reverts::RevertToSlot::Some" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + value, + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + ] + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ M.read (| updated_storage |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let key := M.copy (| ฮณ1_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::Entry") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot" + ], + "or_insert", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ previous_storage; M.read (| key |) ] + |); + Value.StructTuple + "revm::db::states::reverts::RevertToSlot::Destroyed" + [] + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.alloc (| + Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", M.read (| account |)); + ("storage", M.read (| previous_storage |)); + ("previous_status", M.read (| status |)); + ("wipe_storage", Value.Bool false) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_selfdestructed_again : + M.IsAssociatedFunction Self "new_selfdestructed_again" new_selfdestructed_again. + + (* + pub fn new_selfdestructed_from_bundle( + account_info_revert: AccountInfoRevert, + bundle_account: &mut BundleAccount, + updated_storage: &StorageWithOriginalValues, + ) -> Option { + match bundle_account.status { + AccountStatus::InMemoryChange + | AccountStatus::Changed + | AccountStatus::LoadedEmptyEIP161 + | AccountStatus::Loaded => { + let mut ret = AccountRevert::new_selfdestructed_again( + bundle_account.status, + account_info_revert, + bundle_account.storage.drain().collect(), + updated_storage.clone(), + ); + ret.wipe_storage = true; + Some(ret) + } + _ => None, + } + } + *) + Definition new_selfdestructed_from_bundle (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ account_info_revert; bundle_account; updated_storage ] => + ltac:(M.monadic + (let account_info_revert := M.alloc (| account_info_revert |) in + let bundle_account := M.alloc (| bundle_account |) in + let updated_storage := M.alloc (| updated_storage |) in + M.read (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.read (| bundle_account |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::InMemoryChange" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Changed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::LoadedEmptyEIP161" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Loaded" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ ret := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::reverts::AccountRevert", + "new_selfdestructed_again", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| bundle_account |), + "revm::db::states::bundle_account::BundleAccount", + "status" + |) + |); + M.read (| account_info_revert |); + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::Drain") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "drain", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| bundle_account |), + "revm::db::states::bundle_account::BundleAccount", + "storage" + |) + ] + |) + ] + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ M.read (| updated_storage |) ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + ret, + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ M.read (| ret |) ] + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_selfdestructed_from_bundle : + M.IsAssociatedFunction + Self + "new_selfdestructed_from_bundle" + new_selfdestructed_from_bundle. + + (* + pub fn new_selfdestructed( + status: AccountStatus, + account: AccountInfoRevert, + mut storage: StorageWithOriginalValues, + ) -> Self { + // Zero all present storage values and save present values to AccountRevert. + let previous_storage = storage + .iter_mut() + .map(|(key, value)| { + // take previous value and set ZERO as storage got destroyed. + ( *key, RevertToSlot::Some(value.present_value)) + }) + .collect(); + + Self { + account, + storage: previous_storage, + previous_status: status, + wipe_storage: true, + } + } + *) + Definition new_selfdestructed (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ status; account; storage ] => + ltac:(M.monadic + (let status := M.alloc (| status |) in + let account := M.alloc (| account |) in + let storage := M.alloc (| storage |) in + M.read (| + let~ previous_storage := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "std::collections::hash::map::IterMut") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IterMut") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "map", + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot" + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "iter_mut", + [] + |), + [ storage ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let key := M.copy (| ฮณ0_0 |) in + let value := M.copy (| ฮณ0_1 |) in + Value.Tuple + [ + M.read (| M.read (| key |) |); + Value.StructTuple + "revm::db::states::reverts::RevertToSlot::Some" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| value |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + ] + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::db::states::reverts::AccountRevert" + [ + ("account", M.read (| account |)); + ("storage", M.read (| previous_storage |)); + ("previous_status", M.read (| status |)); + ("wipe_storage", Value.Bool true) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_selfdestructed : + M.IsAssociatedFunction Self "new_selfdestructed" new_selfdestructed. + + (* + pub fn is_empty(&self) -> bool { + self.account == AccountInfoRevert::DoNothing + && self.storage.is_empty() + && !self.wipe_storage + } + *) + Definition is_empty (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::reverts::AccountInfoRevert", + [ Ty.path "revm::db::states::reverts::AccountInfoRevert" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "account" + |); + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DoNothing" + [] + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm::db::states::reverts::RevertToSlot"; + Ty.path "std::hash::random::RandomState" + ], + "is_empty", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "storage" + |) + ] + |))) + |), + ltac:(M.monadic + (UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::reverts::AccountRevert", + "wipe_storage" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_empty : M.IsAssociatedFunction Self "is_empty" is_empty. + End Impl_revm_db_states_reverts_AccountRevert. + + (* + Enum AccountInfoRevert + { + ty_params := []; + variants := + [ + { + name := "DoNothing"; + item := StructTuple []; + discriminant := None; + }; + { + name := "DeleteIt"; + item := StructTuple []; + discriminant := None; + }; + { + name := "RevertTo"; + item := StructTuple [ Ty.path "revm_primitives::state::AccountInfo" ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_db_states_reverts_AccountInfoRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountInfoRevert". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::DoNothing" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DoNothing" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + [] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::RevertTo", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm::db::states::reverts::AccountInfoRevert::RevertTo" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::AccountInfo", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_reverts_AccountInfoRevert. + + Module Impl_core_default_Default_for_revm_db_states_reverts_AccountInfoRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountInfoRevert". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructTuple "revm::db::states::reverts::AccountInfoRevert::DoNothing" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_reverts_AccountInfoRevert. + + Module Impl_core_fmt_Debug_for_revm_db_states_reverts_AccountInfoRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountInfoRevert". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::DoNothing" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "DoNothing" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::DeleteIt" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "DeleteIt" |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::RevertTo", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "RevertTo" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_reverts_AccountInfoRevert. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_reverts_AccountInfoRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountInfoRevert". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_reverts_AccountInfoRevert. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_reverts_AccountInfoRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountInfoRevert". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::reverts::AccountInfoRevert" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::reverts::AccountInfoRevert" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm::db::states::reverts::AccountInfoRevert::RevertTo", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm::db::states::reverts::AccountInfoRevert::RevertTo", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::state::AccountInfo", + [ Ty.path "revm_primitives::state::AccountInfo" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool true |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_reverts_AccountInfoRevert. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_reverts_AccountInfoRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountInfoRevert". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_reverts_AccountInfoRevert. + + Module Impl_core_cmp_Eq_for_revm_db_states_reverts_AccountInfoRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountInfoRevert". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_reverts_AccountInfoRevert. + + Module Impl_core_hash_Hash_for_revm_db_states_reverts_AccountInfoRevert. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::AccountInfoRevert". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::reverts::AccountInfoRevert" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "isize", + [], + "hash", + [ __H ] + |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::db::states::reverts::AccountInfoRevert::RevertTo", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "revm_primitives::state::AccountInfo", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_db_states_reverts_AccountInfoRevert. + + (* + Enum RevertToSlot + { + ty_params := []; + variants := + [ + { + name := "Some"; + item := StructTuple [ Ty.path "ruint::Uint" ]; + discriminant := None; + }; + { + name := "Destroyed"; + item := StructTuple []; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_clone_Clone_for_revm_db_states_reverts_RevertToSlot. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::RevertToSlot". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_reverts_RevertToSlot. + + Module Impl_core_fmt_Debug_for_revm_db_states_reverts_RevertToSlot. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::RevertToSlot". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::db::states::reverts::RevertToSlot::Some", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Some" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::RevertToSlot::Destroyed" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "write_str", + [] + |), + [ M.read (| f |); M.read (| Value.String "Destroyed" |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_reverts_RevertToSlot. + + Module Impl_core_marker_Copy_for_revm_db_states_reverts_RevertToSlot. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::RevertToSlot". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_db_states_reverts_RevertToSlot. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_reverts_RevertToSlot. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::RevertToSlot". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_reverts_RevertToSlot. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_reverts_RevertToSlot. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::RevertToSlot". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::reverts::RevertToSlot" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::reverts::RevertToSlot" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_0, + "revm::db::states::reverts::RevertToSlot::Some", + 0 + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ0_1, + "revm::db::states::reverts::RevertToSlot::Some", + 0 + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool true |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_reverts_RevertToSlot. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_reverts_RevertToSlot. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::RevertToSlot". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_reverts_RevertToSlot. + + Module Impl_core_cmp_Eq_for_revm_db_states_reverts_RevertToSlot. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::RevertToSlot". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_reverts_RevertToSlot. + + Module Impl_core_hash_Hash_for_revm_db_states_reverts_RevertToSlot. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::RevertToSlot". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::db::states::reverts::RevertToSlot" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "isize", + [], + "hash", + [ __H ] + |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::db::states::reverts::RevertToSlot::Some", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_db_states_reverts_RevertToSlot. + + Module Impl_revm_db_states_reverts_RevertToSlot. + Definition Self : Ty.t := Ty.path "revm::db::states::reverts::RevertToSlot". + + (* + pub fn to_previous_value(self) -> U256 { + match self { + RevertToSlot::Some(value) => value, + RevertToSlot::Destroyed => U256::ZERO, + } + } + *) + Definition to_previous_value (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::db::states::reverts::RevertToSlot::Some", + 0 + |) in + let value := M.copy (| ฮณ0_0 |) in + value)); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::reverts::RevertToSlot::Destroyed" + |) in + M.get_constant (| "ruint::ZERO" |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_to_previous_value : + M.IsAssociatedFunction Self "to_previous_value" to_previous_value. + End Impl_revm_db_states_reverts_RevertToSlot. + End reverts. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/state.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/state.md new file mode 100644 index 00000000..b516d458 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/state.md @@ -0,0 +1,3316 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/state.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module state. + Axiom DBBox : + forall (E : Ty.t), + (Ty.apply (Ty.path "revm::db::states::state::DBBox") [ E ]) = + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("revm_primitives::db::Database::Trait", []); + ("core::marker::Send::AutoTrait", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom StateDBBox : + forall (E : Ty.t), + (Ty.apply (Ty.path "revm::db::states::state::StateDBBox") [ E ]) = + (Ty.apply + (Ty.path "revm::db::states::state::State") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("revm_primitives::db::Database::Trait", []); + ("core::marker::Send::AutoTrait", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ]). + + (* StructRecord + { + name := "State"; + ty_params := [ "DB" ]; + fields := + [ + ("cache", Ty.path "revm::db::states::cache::CacheState"); + ("database", DB); + ("transition_state", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::transition_state::TransitionState" ]); + ("bundle_state", Ty.path "revm::db::states::bundle_state::BundleState"); + ("use_preloaded_bundle", Ty.path "bool"); + ("block_hashes", + Ty.apply + (Ty.path "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_core_fmt_Debug_where_core_fmt_Debug_DB_for_revm_db_states_state_State_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state::State") [ DB ]. + + (* Debug *) + Definition fmt (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "cache" |); + M.read (| Value.String "database" |); + M.read (| Value.String "transition_state" |); + M.read (| Value.String "bundle_state" |); + M.read (| Value.String "use_preloaded_bundle" |); + M.read (| Value.String "block_hashes" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "cache" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "database" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "transition_state" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "bundle_state" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "use_preloaded_bundle" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "block_hashes" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "State" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt DB)) ]. + End Impl_core_fmt_Debug_where_core_fmt_Debug_DB_for_revm_db_states_state_State_DB. + + Module Impl_revm_db_states_state_State_revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + Definition Self : Ty.t := + Ty.apply + (Ty.path "revm::db::states::state::State") + [ + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ]. + + (* + pub fn builder() -> StateBuilder { + StateBuilder::default() + } + *) + Definition builder (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::db::states::state_builder::StateBuilder") + [ + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + [], + "default", + [] + |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_builder : M.IsAssociatedFunction Self "builder" builder. + End Impl_revm_db_states_state_State_revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + + Module Impl_revm_db_states_state_State_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state::State") [ DB ]. + + (* + pub fn bundle_size_hint(&self) -> usize { + self.bundle_state.size_hint() + } + *) + Definition bundle_size_hint (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleState", + "size_hint", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "bundle_state" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_bundle_size_hint : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "bundle_size_hint" (bundle_size_hint DB). + + (* + pub fn increment_balances( + &mut self, + balances: impl IntoIterator, + ) -> Result<(), DB::Error> { + // make transition and update cache state + let mut transitions = Vec::new(); + for (address, balance) in balances { + if balance == 0 { + continue; + } + let original_account = self.load_cache_account(address)?; + transitions.push(( + address, + original_account + .increment_balance(balance) + .expect("Balance is not zero"), + )) + } + // append transition + if let Some(s) = self.transition_state.as_mut() { + s.add_transitions(transitions) + } + Ok(()) + } + *) + Definition increment_balances (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ impl_IntoIterator_Item____Address__u128__ ], [ self; balances ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let balances := M.alloc (| balances |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ transitions := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + impl_IntoIterator_Item____Address__u128__, + [], + "into_iter", + [] + |), + [ M.read (| balances |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let address := M.copy (| ฮณ1_0 |) in + let balance := M.copy (| ฮณ1_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| balance |)) + (Value.Integer 0) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.continue (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ original_account := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::cache_account::CacheAccount" + ]; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::db::states::state::State") + [ DB ], + "load_cache_account", + [] + |), + [ + M.read (| self |); + M.read (| address |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ Ty.tuple []; Ty.associated + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + transitions; + Value.Tuple + [ + M.read (| address |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::cache_account::CacheAccount", + "increment_balance", + [] + |), + [ + M.read (| original_account |); + M.read (| balance |) + ] + |); + M.read (| + Value.String "Balance is not zero" + |) + ] + |) + ] + ] + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::transition_state::TransitionState" + ], + "as_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "transition_state" + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let s := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::transition_state::TransitionState", + "add_transitions", + [] + |), + [ M.read (| s |); M.read (| transitions |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_increment_balances : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "increment_balances" (increment_balances DB). + + (* + pub fn drain_balances( + &mut self, + addresses: impl IntoIterator, + ) -> Result, DB::Error> { + // make transition and update cache state + let mut transitions = Vec::new(); + let mut balances = Vec::new(); + for address in addresses { + let original_account = self.load_cache_account(address)?; + let (balance, transition) = original_account.drain_balance(); + balances.push(balance); + transitions.push((address, transition)) + } + // append transition + if let Some(s) = self.transition_state.as_mut() { + s.add_transitions(transitions) + } + Ok(balances) + } + *) + Definition drain_balances (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ impl_IntoIterator_Item___Address_ ], [ self; addresses ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let addresses := M.alloc (| addresses |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ transitions := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + |) in + let~ balances := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "u128"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + impl_IntoIterator_Item___Address_, + [], + "into_iter", + [] + |), + [ M.read (| addresses |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.associated, + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let address := M.copy (| ฮณ0_0 |) in + let~ original_account := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::cache_account::CacheAccount" + ]; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::db::states::state::State") + [ DB ], + "load_cache_account", + [] + |), + [ + M.read (| self |); + M.read (| address |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path "u128"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.associated + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::cache_account::CacheAccount", + "drain_balance", + [] + |), + [ M.read (| original_account |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := + M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let balance := M.copy (| ฮณ0_0 |) in + let transition := M.copy (| ฮณ0_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "u128"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ balances; M.read (| balance |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + transitions; + Value.Tuple + [ + M.read (| address |); + M.read (| transition |) + ] + ] + |) + |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::transition_state::TransitionState" + ], + "as_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "transition_state" + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let s := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::transition_state::TransitionState", + "add_transitions", + [] + |), + [ M.read (| s |); M.read (| transitions |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ M.read (| balances |) ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_drain_balances : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "drain_balances" (drain_balances DB). + + (* + pub fn set_state_clear_flag(&mut self, has_state_clear: bool) { + self.cache.set_state_clear_flag(has_state_clear); + } + *) + Definition set_state_clear_flag (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; has_state_clear ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let has_state_clear := M.alloc (| has_state_clear |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache::CacheState", + "set_state_clear_flag", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "cache" + |); + M.read (| has_state_clear |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_state_clear_flag : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "set_state_clear_flag" (set_state_clear_flag DB). + + (* + pub fn insert_not_existing(&mut self, address: Address) { + self.cache.insert_not_existing(address) + } + *) + Definition insert_not_existing (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache::CacheState", + "insert_not_existing", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "cache" + |); + M.read (| address |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_not_existing : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "insert_not_existing" (insert_not_existing DB). + + (* + pub fn insert_account(&mut self, address: Address, info: AccountInfo) { + self.cache.insert_account(address, info) + } + *) + Definition insert_account (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address; info ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let info := M.alloc (| info |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache::CacheState", + "insert_account", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "cache" + |); + M.read (| address |); + M.read (| info |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_account : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "insert_account" (insert_account DB). + + (* + pub fn insert_account_with_storage( + &mut self, + address: Address, + info: AccountInfo, + storage: PlainStorage, + ) { + self.cache + .insert_account_with_storage(address, info, storage) + } + *) + Definition insert_account_with_storage (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address; info; storage ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let info := M.alloc (| info |) in + let storage := M.alloc (| storage |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache::CacheState", + "insert_account_with_storage", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "cache" + |); + M.read (| address |); + M.read (| info |); + M.read (| storage |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_account_with_storage : + forall (DB : Ty.t), + M.IsAssociatedFunction + (Self DB) + "insert_account_with_storage" + (insert_account_with_storage DB). + + (* + pub fn apply_transition(&mut self, transitions: Vec<(Address, TransitionAccount)>) { + // add transition to transition state. + if let Some(s) = self.transition_state.as_mut() { + s.add_transitions(transitions) + } + } + *) + Definition apply_transition (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; transitions ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let transitions := M.alloc (| transitions |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::transition_state::TransitionState" ], + "as_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "transition_state" + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let s := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::transition_state::TransitionState", + "add_transitions", + [] + |), + [ M.read (| s |); M.read (| transitions |) ] + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_apply_transition : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "apply_transition" (apply_transition DB). + + (* + pub fn merge_transitions(&mut self, retention: BundleRetention) { + if let Some(transition_state) = self.transition_state.as_mut().map(TransitionState::take) { + self.bundle_state + .apply_transitions_and_create_reverts(transition_state, retention); + } + } + *) + Definition merge_transitions (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; retention ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let retention := M.alloc (| retention |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::transition_state::TransitionState" + ] + ], + "map", + [ + Ty.path "revm::db::states::transition_state::TransitionState"; + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::transition_state::TransitionState" + ] + ] + (Ty.path "revm::db::states::transition_state::TransitionState") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::transition_state::TransitionState" + ], + "as_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "transition_state" + |) + ] + |); + M.get_associated_function (| + Ty.path "revm::db::states::transition_state::TransitionState", + "take", + [] + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let transition_state := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_state::BundleState", + "apply_transitions_and_create_reverts", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "bundle_state" + |); + M.read (| transition_state |); + M.read (| retention |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_merge_transitions : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "merge_transitions" (merge_transitions DB). + + (* + pub fn load_cache_account(&mut self, address: Address) -> Result<&mut CacheAccount, DB::Error> { + match self.cache.accounts.entry(address) { + hash_map::Entry::Vacant(entry) => { + if self.use_preloaded_bundle { + // load account from bundle state + if let Some(account) = + self.bundle_state.account(&address).cloned().map(Into::into) + { + return Ok(entry.insert(account)); + } + } + // if not found in bundle, load it from database + let info = self.database.basic(address)?; + let account = match info { + None => CacheAccount::new_loaded_not_existing(), + Some(acc) if acc.is_empty() => { + CacheAccount::new_loaded_empty_eip161(HashMap::new()) + } + Some(acc) => CacheAccount::new_loaded(acc, HashMap::new()), + }; + Ok(entry.insert(account)) + } + hash_map::Entry::Occupied(entry) => Ok(entry.into_mut()), + } + } + *) + Definition load_cache_account (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "cache" + |), + "revm::db::states::cache::CacheState", + "accounts" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "use_preloaded_bundle" + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ], + "map", + [ + Ty.path + "revm::db::states::cache_account::CacheAccount"; + Ty.function + [ + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ] + (Ty.path + "revm::db::states::cache_account::CacheAccount") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm::db::states::bundle_account::BundleAccount" + ] + ], + "cloned", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::bundle_state::BundleState", + "account", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "bundle_state" + |); + address + ] + |) + ] + |); + M.get_trait_method (| + "core::convert::Into", + Ty.path + "revm::db::states::bundle_account::BundleAccount", + [ + Ty.path + "revm::db::states::cache_account::CacheAccount" + ], + "into", + [] + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let account := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::cache_account::CacheAccount" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.read (| account |) + ] + |) + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ info := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "basic", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "database" + |); + M.read (| address |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::cache_account::CacheAccount" + ]; + Ty.associated + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ account := + M.copy (| + M.match_operator (| + info, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::cache_account::CacheAccount", + "new_loaded_not_existing", + [] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let acc := M.copy (| ฮณ0_0 |) in + let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::AccountInfo", + "is_empty", + [] + |), + [ acc ] + |) + |) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::cache_account::CacheAccount", + "new_loaded_empty_eip161", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let acc := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::cache_account::CacheAccount", + "new_loaded", + [] + |), + [ + M.read (| acc |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |) + ] + |) + |))) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount" + ], + "insert", + [] + |), + [ M.read (| entry |); M.read (| account |) ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount" + ], + "into_mut", + [] + |), + [ M.read (| entry |) ] + |) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_cache_account : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "load_cache_account" (load_cache_account DB). + + (* + pub fn take_bundle(&mut self) -> BundleState { + core::mem::take(&mut self.bundle_state) + } + *) + Definition take_bundle (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_function (| + "core::mem::take", + [ Ty.path "revm::db::states::bundle_state::BundleState" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "bundle_state" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_take_bundle : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "take_bundle" (take_bundle DB). + End Impl_revm_db_states_state_State_DB. + + Module Impl_revm_primitives_db_Database_where_revm_primitives_db_Database_DB_for_revm_db_states_state_State_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state::State") [ DB ]. + + (* type Error = DB::Error; *) + Definition _Error (DB : Ty.t) : Ty.t := Ty.associated. + + (* + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.load_cache_account(address).map(|a| a.account_info()) + } + *) + Definition basic (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm::db::states::cache_account::CacheAccount" ]; + Ty.associated + ], + "map", + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm::db::states::cache_account::CacheAccount" ] + ] + ] + (Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::states::state::State") [ DB ], + "load_cache_account", + [] + |), + [ M.read (| self |); M.read (| address |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let a := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache_account::CacheAccount", + "account_info", + [] + |), + [ M.read (| a |) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn code_by_hash(&mut self, code_hash: B256) -> Result { + let res = match self.cache.contracts.entry(code_hash) { + hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()), + hash_map::Entry::Vacant(entry) => { + if self.use_preloaded_bundle { + if let Some(code) = self.bundle_state.contracts.get(&code_hash) { + entry.insert(code.clone()); + return Ok(code.clone()); + } + } + // if not found in bundle ask database + let code = self.database.code_by_hash(code_hash)?; + entry.insert(code.clone()); + Ok(code) + } + }; + res + } + *) + Definition code_by_hash (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; code_hash ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let code_hash := M.alloc (| code_hash |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ res := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "cache" + |), + "revm::db::states::cache::CacheState", + "contracts" + |); + M.read (| code_hash |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ], + "get", + [] + |), + [ entry ] + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "use_preloaded_bundle" + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path + "revm_primitives::bytecode::Bytecode"; + Ty.path + "std::hash::random::RandomState" + ], + "get", + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "bundle_state" + |), + "revm::db::states::bundle_state::BundleState", + "contracts" + |); + code_hash + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let code := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path + "revm_primitives::bytecode::Bytecode" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ M.read (| code |) ] + |) + ] + |) + |) in + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ M.read (| code |) ] + |) + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ code := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::bytecode::Bytecode"; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "code_by_hash", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "database" + |); + M.read (| code_hash |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_primitives::bytecode::Bytecode"; + Ty.associated + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "revm_primitives::bytecode::Bytecode" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "clone", + [] + |), + [ code ] + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ M.read (| code |) ] + |))) + ] + |) + |) in + res + |))) + |))) + | _, _ => M.impossible + end. + + (* + fn storage(&mut self, address: Address, index: U256) -> Result { + // Account is guaranteed to be loaded. + // Note that storage from bundle is already loaded with account. + if let Some(account) = self.cache.accounts.get_mut(&address) { + // account will always be some, but if it is not, U256::ZERO will be returned. + let is_storage_known = account.status.is_storage_known(); + Ok(account + .account + .as_mut() + .map(|account| match account.storage.entry(index) { + hash_map::Entry::Occupied(entry) => Ok( *entry.get()), + hash_map::Entry::Vacant(entry) => { + // if account was destroyed or account is newly built + // we return zero and don't ask database. + let value = if is_storage_known { + U256::ZERO + } else { + self.database.storage(address, index)? + }; + entry.insert(value); + Ok(value) + } + }) + .transpose()? + .unwrap_or_default()) + } else { + unreachable!("For accessing any storage account is guaranteed to be loaded beforehand") + } + } + *) + Definition storage (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::cache_account::CacheAccount"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "cache" + |), + "revm::db::states::cache::CacheState", + "accounts" + |); + address + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let account := M.copy (| ฮณ0_0 |) in + let~ is_storage_known := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::account_status::AccountStatus", + "is_storage_known", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm::db::states::cache_account::CacheAccount", + "status" + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + "unwrap_or_default", + [] + |), + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ]; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "ruint::Uint"; Ty.associated ] + ], + "transpose", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::plain_account::PlainAccount" + ] + ], + "map", + [ + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "ruint::Uint"; Ty.associated + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::db::states::plain_account::PlainAccount" + ] + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "ruint::Uint"; Ty.associated + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm::db::states::plain_account::PlainAccount" + ], + "as_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm::db::states::cache_account::CacheAccount", + "account" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let account := + M.copy (| ฮณ |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint"; + Ty.path + "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + account + |), + "revm::db::states::plain_account::PlainAccount", + "storage" + |); + M.read (| index |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := + M.copy (| + ฮณ0_0 + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ], + "get", + [] + |), + [ entry + ] + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := + M.copy (| + ฮณ0_0 + |) in + let~ value := + M.copy (| + M.match_operator (| + M.alloc (| + Value.Tuple + [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let + ฮณ := + M.use + is_storage_known in + let + _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Bool + true + |) in + M.get_constant (| + "ruint::ZERO" + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "ruint::Uint"; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "storage", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + self + |), + "revm::db::states::state::State", + "database" + |); + M.read (| + address + |); + M.read (| + index + |) + ] + |) + ] + |) + |), + [ + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let + residual := + M.copy (| + ฮณ0_0 + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "ruint::Uint"; + Ty.associated + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun + ฮณ => + ltac:(M.monadic + (let + ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let + val := + M.copy (| + ฮณ0_0 + |) in + val)) + ] + |))) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ + Ty.path + "ruint::Uint"; + Ty.path + "ruint::Uint" + ], + "insert", + [] + |), + [ + M.read (| + entry + |); + M.read (| + value + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.read (| + value + |) + ] + |))) + ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "ruint::Uint"; Ty.associated + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: For accessing any storage account is guaranteed to be loaded beforehand" + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "none", + [] + |), + [] + |) + |)) + ] + |) + ] + |) + |) + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + (* + fn block_hash(&mut self, number: U256) -> Result { + // block number is never bigger then u64::MAX. + let u64num: u64 = number.to(); + match self.block_hashes.entry(u64num) { + btree_map::Entry::Occupied(entry) => Ok( *entry.get()), + btree_map::Entry::Vacant(entry) => { + let ret = *entry.insert(self.database.block_hash(number)?); + + // prune all hashes that are older then BLOCK_HASH_HISTORY + while let Some(entry) = self.block_hashes.first_entry() { + if *entry.key() < u64num.saturating_sub(BLOCK_HASH_HISTORY as u64) { + entry.remove(); + } else { + break; + } + } + + Ok(ret) + } + } + } + *) + Definition block_hash (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ u64num := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "to", + [ Ty.path "u64" ] + |), + [ number ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "block_hashes" + |); + M.read (| u64num |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "alloc::collections::btree::map::entry::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::collections::btree::map::entry::OccupiedEntry") + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "get", + [] + |), + [ entry ] + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "alloc::collections::btree::map::entry::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ ret := + M.copy (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::collections::btree::map::entry::VacantEntry") + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.associated + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "block_hash", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "database" + |); + M.read (| number |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.associated + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.associated + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |) + |) in + let~ _ := + M.loop (| + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "first_entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "block_hashes" + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.lt + (M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::collections::btree::map::entry::OccupiedEntry") + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "key", + [] + |), + [ entry ] + |) + |)) + (M.call_closure (| + M.get_associated_function (| + Ty.path "u64", + "saturating_sub", + [] + |), + [ + M.read (| u64num |); + M.rust_cast + (M.read (| + M.get_constant (| + "revm_primitives::constants::BLOCK_HASH_HISTORY" + |) + |)) + ] + |)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::collections::btree::map::entry::OccupiedEntry") + [ + Ty.path "u64"; + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "remove", + [] + |), + [ M.read (| entry |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |) in + M.alloc (| Value.Tuple [] |) + |) + |) + |))) + ] + |))) + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ M.read (| ret |) ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "revm_primitives::db::Database" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("Error", InstanceField.Ty (_Error DB)); + ("basic", InstanceField.Method (basic DB)); + ("code_by_hash", InstanceField.Method (code_by_hash DB)); + ("storage", InstanceField.Method (storage DB)); + ("block_hash", InstanceField.Method (block_hash DB)) + ]. + End Impl_revm_primitives_db_Database_where_revm_primitives_db_Database_DB_for_revm_db_states_state_State_DB. + + Module Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_Database_DB_for_revm_db_states_state_State_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state::State") [ DB ]. + + (* + fn commit(&mut self, evm_state: HashMap) { + let transitions = self.cache.apply_evm_state(evm_state); + self.apply_transition(transitions); + } + *) + Definition commit (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; evm_state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let evm_state := M.alloc (| evm_state |) in + M.read (| + let~ transitions := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache::CacheState", + "apply_evm_state", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state::State", + "cache" + |); + M.read (| evm_state |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::states::state::State") [ DB ], + "apply_transition", + [] + |), + [ M.read (| self |); M.read (| transitions |) ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "revm_primitives::db::DatabaseCommit" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("commit", InstanceField.Method (commit DB)) ]. + End Impl_revm_primitives_db_DatabaseCommit_where_revm_primitives_db_Database_DB_for_revm_db_states_state_State_DB. + End state. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/state_builder.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/state_builder.md new file mode 100644 index 00000000..8a5f698e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/state_builder.md @@ -0,0 +1,1263 @@ +# ๐Ÿ“ state_builder.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/state_builder.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module state_builder. + (* StructRecord + { + name := "StateBuilder"; + ty_params := [ "DB" ]; + fields := + [ + ("database", DB); + ("with_state_clear", Ty.path "bool"); + ("with_bundle_prestate", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::bundle_state::BundleState" ]); + ("with_cache_prestate", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::cache::CacheState" ]); + ("with_bundle_update", Ty.path "bool"); + ("with_background_transition_merge", Ty.path "bool"); + ("with_block_hashes", + Ty.apply + (Ty.path "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_where_core_clone_Clone_DB_for_revm_db_states_state_builder_StateBuilder_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ]. + + (* Clone *) + Definition clone (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::state_builder::StateBuilder" + [ + ("database", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", DB, [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "database" + |) + ] + |)); + ("with_state_clear", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_state_clear" + |) + ] + |)); + ("with_bundle_prestate", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::bundle_state::BundleState" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_bundle_prestate" + |) + ] + |)); + ("with_cache_prestate", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::cache::CacheState" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_cache_prestate" + |) + ] + |)); + ("with_bundle_update", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_bundle_update" + |) + ] + |)); + ("with_background_transition_merge", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_background_transition_merge" + |) + ] + |)); + ("with_block_hashes", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_block_hashes" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::clone::Clone" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method (clone DB)) ]. + End Impl_core_clone_Clone_where_core_clone_Clone_DB_for_revm_db_states_state_builder_StateBuilder_DB. + + Module Impl_core_fmt_Debug_where_core_fmt_Debug_DB_for_revm_db_states_state_builder_StateBuilder_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ]. + + (* Debug *) + Definition fmt (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "database" |); + M.read (| Value.String "with_state_clear" |); + M.read (| Value.String "with_bundle_prestate" |); + M.read (| Value.String "with_cache_prestate" |); + M.read (| Value.String "with_bundle_update" |); + M.read (| Value.String "with_background_transition_merge" |); + M.read (| Value.String "with_block_hashes" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "database" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_state_clear" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_bundle_prestate" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_cache_prestate" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_bundle_update" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_background_transition_merge" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_block_hashes" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "StateBuilder" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt DB)) ]. + End Impl_core_fmt_Debug_where_core_fmt_Debug_DB_for_revm_db_states_state_builder_StateBuilder_DB. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_state_builder_StateBuilder_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ]. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::marker::StructuralPartialEq" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_state_builder_StateBuilder_DB. + + Module Impl_core_cmp_PartialEq_where_core_cmp_PartialEq_DB_for_revm_db_states_state_builder_StateBuilder_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ]. + + (* PartialEq *) + Definition eq (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| "core::cmp::PartialEq", DB, [ DB ], "eq", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "database" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::state_builder::StateBuilder", + "database" + |) + ] + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_state_clear" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::state_builder::StateBuilder", + "with_state_clear" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::bundle_state::BundleState" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::bundle_state::BundleState" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_bundle_prestate" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::state_builder::StateBuilder", + "with_bundle_prestate" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::cache::CacheState" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::cache::CacheState" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_cache_prestate" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::state_builder::StateBuilder", + "with_cache_prestate" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_bundle_update" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::state_builder::StateBuilder", + "with_bundle_update" + |) + |)))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_background_transition_merge" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::state_builder::StateBuilder", + "with_background_transition_merge" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::state_builder::StateBuilder", + "with_block_hashes" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::state_builder::StateBuilder", + "with_block_hashes" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::cmp::PartialEq" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method (eq DB)) ]. + End Impl_core_cmp_PartialEq_where_core_cmp_PartialEq_DB_for_revm_db_states_state_builder_StateBuilder_DB. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_state_builder_StateBuilder_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ]. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::marker::StructuralEq" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_state_builder_StateBuilder_DB. + + Module Impl_core_cmp_Eq_where_core_cmp_Eq_DB_for_revm_db_states_state_builder_StateBuilder_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ]. + + (* Eq *) + Definition assert_receiver_is_total_eq (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::cmp::Eq" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method (assert_receiver_is_total_eq DB)) + ]. + End Impl_core_cmp_Eq_where_core_cmp_Eq_DB_for_revm_db_states_state_builder_StateBuilder_DB. + + Module Impl_revm_db_states_state_builder_StateBuilder_revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + Definition Self : Ty.t := + Ty.apply + (Ty.path "revm::db::states::state_builder::StateBuilder") + [ + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ]. + + (* + pub fn new() -> Self { + Self::default() + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::db::states::state_builder::StateBuilder") + [ + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + [], + "default", + [] + |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + End Impl_revm_db_states_state_builder_StateBuilder_revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + + Module Impl_core_default_Default_where_revm_primitives_db_Database_DB_where_core_default_Default_DB_for_revm_db_states_state_builder_StateBuilder_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ]. + + (* + fn default() -> Self { + Self::new_with_database(DB::default()) + } + *) + Definition default (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ], + "new_with_database", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| "core::default::Default", DB, [], "default", [] |), + [] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "core::default::Default" + (Self DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method (default DB)) ]. + End Impl_core_default_Default_where_revm_primitives_db_Database_DB_where_core_default_Default_DB_for_revm_db_states_state_builder_StateBuilder_DB. + + Module Impl_revm_db_states_state_builder_StateBuilder_DB. + Definition Self (DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ]. + + (* + pub fn new_with_database(database: DB) -> Self { + Self { + database, + with_state_clear: true, + with_cache_prestate: None, + with_bundle_prestate: None, + with_bundle_update: false, + with_background_transition_merge: false, + with_block_hashes: BTreeMap::new(), + } + } + *) + Definition new_with_database (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ database ] => + ltac:(M.monadic + (let database := M.alloc (| database |) in + Value.StructRecord + "revm::db::states::state_builder::StateBuilder" + [ + ("database", M.read (| database |)); + ("with_state_clear", Value.Bool true); + ("with_cache_prestate", Value.StructTuple "core::option::Option::None" []); + ("with_bundle_prestate", Value.StructTuple "core::option::Option::None" []); + ("with_bundle_update", Value.Bool false); + ("with_background_transition_merge", Value.Bool false); + ("with_block_hashes", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::collections::btree::map::BTreeMap") + [ + Ty.path "u64"; + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_with_database : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "new_with_database" (new_with_database DB). + + (* + pub fn with_database(self, database: ODB) -> StateBuilder { + // cast to the different database, + // Note that we return different type depending of the database NewDBError. + StateBuilder { + with_state_clear: self.with_state_clear, + database, + with_cache_prestate: self.with_cache_prestate, + with_bundle_prestate: self.with_bundle_prestate, + with_bundle_update: self.with_bundle_update, + with_background_transition_merge: self.with_background_transition_merge, + with_block_hashes: self.with_block_hashes, + } + } + *) + Definition with_database (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ ODB ], [ self; database ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let database := M.alloc (| database |) in + Value.StructRecord + "revm::db::states::state_builder::StateBuilder" + [ + ("with_state_clear", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_state_clear" + |) + |)); + ("database", M.read (| database |)); + ("with_cache_prestate", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_cache_prestate" + |) + |)); + ("with_bundle_prestate", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_bundle_prestate" + |) + |)); + ("with_bundle_update", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_bundle_update" + |) + |)); + ("with_background_transition_merge", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_background_transition_merge" + |) + |)); + ("with_block_hashes", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_block_hashes" + |) + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_database : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "with_database" (with_database DB). + + (* + pub fn with_database_ref( + self, + database: ODB, + ) -> StateBuilder> { + self.with_database(WrapDatabaseRef(database)) + } + *) + Definition with_database_ref (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ ODB ], [ self; database ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let database := M.alloc (| database |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ], + "with_database", + [ Ty.apply (Ty.path "revm_primitives::db::WrapDatabaseRef") [ ODB ] ] + |), + [ + M.read (| self |); + Value.StructTuple "revm_primitives::db::WrapDatabaseRef" [ M.read (| database |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_database_ref : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "with_database_ref" (with_database_ref DB). + + (* + pub fn with_database_boxed( + self, + database: DBBox<'_, Error>, + ) -> StateBuilder> { + self.with_database(database) + } + *) + Definition with_database_boxed (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [ Error ], [ self; database ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let database := M.alloc (| database |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::db::states::state_builder::StateBuilder") [ DB ], + "with_database", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("revm_primitives::db::Database::Trait", []); + ("core::marker::Send::AutoTrait", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ M.read (| self |); (* Unsize *) M.pointer_coercion (M.read (| database |)) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_database_boxed : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "with_database_boxed" (with_database_boxed DB). + + (* + pub fn without_state_clear(self) -> Self { + Self { + with_state_clear: false, + ..self + } + } + *) + Definition without_state_clear (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.struct_record_update + (M.read (| self |)) + [ ("with_state_clear", Value.Bool false) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_without_state_clear : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "without_state_clear" (without_state_clear DB). + + (* + pub fn with_bundle_prestate(self, bundle: BundleState) -> Self { + Self { + with_bundle_prestate: Some(bundle), + ..self + } + } + *) + Definition with_bundle_prestate (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; bundle ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let bundle := M.alloc (| bundle |) in + M.struct_record_update + (M.read (| self |)) + [ + ("with_bundle_prestate", + Value.StructTuple "core::option::Option::Some" [ M.read (| bundle |) ]) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_bundle_prestate : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "with_bundle_prestate" (with_bundle_prestate DB). + + (* + pub fn with_bundle_update(self) -> Self { + Self { + with_bundle_update: true, + ..self + } + } + *) + Definition with_bundle_update (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.struct_record_update + (M.read (| self |)) + [ ("with_bundle_update", Value.Bool true) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_bundle_update : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "with_bundle_update" (with_bundle_update DB). + + (* + pub fn with_cached_prestate(self, cache: CacheState) -> Self { + Self { + with_cache_prestate: Some(cache), + ..self + } + } + *) + Definition with_cached_prestate (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; cache ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let cache := M.alloc (| cache |) in + M.struct_record_update + (M.read (| self |)) + [ + ("with_cache_prestate", + Value.StructTuple "core::option::Option::Some" [ M.read (| cache |) ]) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_cached_prestate : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "with_cached_prestate" (with_cached_prestate DB). + + (* + pub fn with_background_transition_merge(self) -> Self { + Self { + with_background_transition_merge: true, + ..self + } + } + *) + Definition with_background_transition_merge + (DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.struct_record_update + (M.read (| self |)) + [ ("with_background_transition_merge", Value.Bool true) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_background_transition_merge : + forall (DB : Ty.t), + M.IsAssociatedFunction + (Self DB) + "with_background_transition_merge" + (with_background_transition_merge DB). + + (* + pub fn with_block_hashes(self, block_hashes: BTreeMap) -> Self { + Self { + with_block_hashes: block_hashes, + ..self + } + } + *) + Definition with_block_hashes (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; block_hashes ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let block_hashes := M.alloc (| block_hashes |) in + M.struct_record_update + (M.read (| self |)) + [ ("with_block_hashes", M.read (| block_hashes |)) ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_with_block_hashes : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "with_block_hashes" (with_block_hashes DB). + + (* + pub fn build(mut self) -> State { + let use_preloaded_bundle = if self.with_cache_prestate.is_some() { + self.with_bundle_prestate = None; + false + } else { + self.with_bundle_prestate.is_some() + }; + State { + cache: self + .with_cache_prestate + .unwrap_or_else(|| CacheState::new(self.with_state_clear)), + database: self.database, + transition_state: self.with_bundle_update.then(TransitionState::default), + bundle_state: self.with_bundle_prestate.unwrap_or_default(), + use_preloaded_bundle, + block_hashes: self.with_block_hashes, + } + } + *) + Definition build (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ use_preloaded_bundle := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::cache::CacheState" ], + "is_some", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_cache_prestate" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_bundle_prestate" + |), + Value.StructTuple "core::option::Option::None" [] + |) in + M.alloc (| Value.Bool false |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::bundle_state::BundleState" ], + "is_some", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_bundle_prestate" + |) + ] + |) + |))) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::db::states::state::State" + [ + ("cache", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::cache::CacheState" ], + "unwrap_or_else", + [ + Ty.function + [ Ty.tuple [] ] + (Ty.path "revm::db::states::cache::CacheState") + ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_cache_prestate" + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::cache::CacheState", + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_state_clear" + |) + |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)); + ("database", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "database" + |) + |)); + ("transition_state", + M.call_closure (| + M.get_associated_function (| + Ty.path "bool", + "then", + [ + Ty.path "revm::db::states::transition_state::TransitionState"; + Ty.function + [] + (Ty.path "revm::db::states::transition_state::TransitionState") + ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_bundle_update" + |) + |); + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::states::transition_state::TransitionState", + [], + "default", + [] + |) + ] + |)); + ("bundle_state", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::db::states::bundle_state::BundleState" ], + "unwrap_or_default", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_bundle_prestate" + |) + |) + ] + |)); + ("use_preloaded_bundle", M.read (| use_preloaded_bundle |)); + ("block_hashes", + M.read (| + M.SubPointer.get_struct_record_field (| + self, + "revm::db::states::state_builder::StateBuilder", + "with_block_hashes" + |) + |)) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_build : + forall (DB : Ty.t), + M.IsAssociatedFunction (Self DB) "build" (build DB). + End Impl_revm_db_states_state_builder_StateBuilder_DB. + End state_builder. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/transition_account.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/transition_account.md new file mode 100644 index 00000000..e2ecce1d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/transition_account.md @@ -0,0 +1,2139 @@ +# ๐Ÿ“ transition_account.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/transition_account.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module transition_account. + (* StructRecord + { + name := "TransitionAccount"; + ty_params := []; + fields := + [ + ("info", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]); + ("status", Ty.path "revm::db::states::account_status::AccountStatus"); + ("previous_info", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ]); + ("previous_status", Ty.path "revm::db::states::account_status::AccountStatus"); + ("storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ]); + ("storage_was_destroyed", Ty.path "bool") + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_transition_account_TransitionAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_account::TransitionAccount". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::transition_account::TransitionAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "info" + |) + ] + |)); + ("status", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::db::states::account_status::AccountStatus", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "status" + |) + ] + |)); + ("previous_info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_info" + |) + ] + |)); + ("previous_status", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::db::states::account_status::AccountStatus", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_status" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage" + |) + ] + |)); + ("storage_was_destroyed", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage_was_destroyed" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_transition_account_TransitionAccount. + + Module Impl_core_fmt_Debug_for_revm_db_states_transition_account_TransitionAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_account::TransitionAccount". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "info" |); + M.read (| Value.String "status" |); + M.read (| Value.String "previous_info" |); + M.read (| Value.String "previous_status" |); + M.read (| Value.String "storage" |); + M.read (| Value.String "storage_was_destroyed" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "info" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "status" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_info" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_status" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage_was_destroyed" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "TransitionAccount" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_transition_account_TransitionAccount. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_transition_account_TransitionAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_account::TransitionAccount". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_transition_account_TransitionAccount. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_transition_account_TransitionAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_account::TransitionAccount". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "info" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::transition_account::TransitionAccount", + "info" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::account_status::AccountStatus", + [ Ty.path "revm::db::states::account_status::AccountStatus" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "status" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::transition_account::TransitionAccount", + "status" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_info" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::transition_account::TransitionAccount", + "previous_info" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm::db::states::account_status::AccountStatus", + [ Ty.path "revm::db::states::account_status::AccountStatus" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_status" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::transition_account::TransitionAccount", + "previous_status" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::transition_account::TransitionAccount", + "storage" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage_was_destroyed" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::transition_account::TransitionAccount", + "storage_was_destroyed" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_transition_account_TransitionAccount. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_transition_account_TransitionAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_account::TransitionAccount". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_transition_account_TransitionAccount. + + Module Impl_core_cmp_Eq_for_revm_db_states_transition_account_TransitionAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_account::TransitionAccount". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_transition_account_TransitionAccount. + + Module Impl_core_default_Default_for_revm_db_states_transition_account_TransitionAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_account::TransitionAccount". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::transition_account::TransitionAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "default", + [] + |), + [] + |)); + ("status", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::states::account_status::AccountStatus", + [], + "default", + [] + |), + [] + |)); + ("previous_info", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "default", + [] + |), + [] + |)); + ("previous_status", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::db::states::account_status::AccountStatus", + [], + "default", + [] + |), + [] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("storage_was_destroyed", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "bool", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_transition_account_TransitionAccount. + + Module Impl_revm_db_states_transition_account_TransitionAccount. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_account::TransitionAccount". + + (* + pub fn new_empty_eip161(storage: StorageWithOriginalValues) -> Self { + Self { + info: Some(AccountInfo::default()), + status: AccountStatus::InMemoryChange, + previous_info: None, + previous_status: AccountStatus::LoadedNotExisting, + storage, + storage_was_destroyed: false, + } + } + *) + Definition new_empty_eip161 (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ storage ] => + ltac:(M.monadic + (let storage := M.alloc (| storage |) in + Value.StructRecord + "revm::db::states::transition_account::TransitionAccount" + [ + ("info", + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::AccountInfo", + [], + "default", + [] + |), + [] + |) + ]); + ("status", + Value.StructTuple + "revm::db::states::account_status::AccountStatus::InMemoryChange" + []); + ("previous_info", Value.StructTuple "core::option::Option::None" []); + ("previous_status", + Value.StructTuple + "revm::db::states::account_status::AccountStatus::LoadedNotExisting" + []); + ("storage", M.read (| storage |)); + ("storage_was_destroyed", Value.Bool false) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_empty_eip161 : + M.IsAssociatedFunction Self "new_empty_eip161" new_empty_eip161. + + (* + pub fn has_new_contract(&self) -> Option<(B256, &Bytecode)> { + let present_new_codehash = self.info.as_ref().map(|info| &info.code_hash); + let previous_codehash = self.previous_info.as_ref().map(|info| &info.code_hash); + if present_new_codehash != previous_codehash { + return self + .info + .as_ref() + .and_then(|info| info.code.as_ref().map(|c| (info.code_hash, c))); + } + None + } + *) + Definition has_new_contract (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ present_new_codehash := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "map", + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + ] + (Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "info" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + M.SubPointer.get_struct_record_field (| + M.read (| info |), + "revm_primitives::state::AccountInfo", + "code_hash" + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ previous_codehash := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "map", + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + ] + (Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_info" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + M.SubPointer.get_struct_record_field (| + M.read (| info |), + "revm_primitives::state::AccountInfo", + "code_hash" + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" + ] + ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ] + ] + ], + "ne", + [] + |), + [ present_new_codehash; previous_codehash ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "and_then", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::bytecode::Bytecode" ] + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ] + ] + ] + (Ty.apply + (Ty.path "core::option::Option") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::bytecode::Bytecode" + ] + ] + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "info" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::bytecode::Bytecode" + ] + ], + "map", + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::bytecode::Bytecode" + ] + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::bytecode::Bytecode" + ] + ] + ] + (Ty.tuple + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes"; + Ty.apply + (Ty.path "&") + [ + Ty.path + "revm_primitives::bytecode::Bytecode" + ] + ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::bytecode::Bytecode" + ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| info |), + "revm_primitives::state::AccountInfo", + "code" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let c := + M.copy (| ฮณ |) in + Value.Tuple + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| + info + |), + "revm_primitives::state::AccountInfo", + "code_hash" + |) + |); + M.read (| c |) + ])) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_has_new_contract : + M.IsAssociatedFunction Self "has_new_contract" has_new_contract. + + (* + pub fn previous_balance(&self) -> U256 { + self.previous_info + .as_ref() + .map(|info| info.balance) + .unwrap_or_default() + } + *) + Definition previous_balance (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "map", + [ + Ty.path "ruint::Uint"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + ] + (Ty.path "ruint::Uint") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_info" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| info |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_previous_balance : + M.IsAssociatedFunction Self "previous_balance" previous_balance. + + (* + pub fn current_balance(&self) -> U256 { + self.info + .as_ref() + .map(|info| info.balance) + .unwrap_or_default() + } + *) + Definition current_balance (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::state::AccountInfo" ] + ], + "map", + [ + Ty.path "ruint::Uint"; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&") + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + ] + (Ty.path "ruint::Uint") + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "as_ref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "info" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let info := M.copy (| ฮณ |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| info |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_current_balance : + M.IsAssociatedFunction Self "current_balance" current_balance. + + (* + pub fn balance_delta(&self) -> Option { + let previous_balance = self.previous_balance(); + let current_balance = self.current_balance(); + let delta = I256::try_from(previous_balance.abs_diff(current_balance)).ok()?; + if current_balance >= previous_balance { + Some(delta) + } else { + delta.checked_neg() + } + } + *) + Definition balance_delta (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ previous_balance := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::transition_account::TransitionAccount", + "previous_balance", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ current_balance := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::transition_account::TransitionAccount", + "current_balance", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ delta := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::signed::int::Signed" ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "alloy_primitives::signed::int::Signed"; + Ty.path + "alloy_primitives::signed::errors::BigIntConversionError" + ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryFrom", + Ty.path "alloy_primitives::signed::int::Signed", + [ Ty.path "ruint::Uint" ], + "try_from", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "abs_diff", + [] + |), + [ + M.read (| previous_balance |); + M.read (| current_balance |) + ] + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "alloy_primitives::signed::int::Signed" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "core::convert::Infallible" ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialOrd", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ge", + [] + |), + [ current_balance; previous_balance ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + Value.StructTuple "core::option::Option::Some" [ M.read (| delta |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "alloy_primitives::signed::int::Signed", + "checked_neg", + [] + |), + [ M.read (| delta |) ] + |) + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_balance_delta : + M.IsAssociatedFunction Self "balance_delta" balance_delta. + + (* + pub fn update(&mut self, other: Self) { + self.info = other.info.clone(); + self.status = other.status; + + // if transition is from some to destroyed drop the storage. + // This need to be done here as it is one increment of the state. + if matches!( + other.status, + AccountStatus::Destroyed | AccountStatus::DestroyedAgain + ) { + self.storage = other.storage; + self.storage_was_destroyed = true; + } else { + // update changed values to this transition. + for (key, slot) in other.storage.into_iter() { + match self.storage.entry(key) { + hash_map::Entry::Vacant(entry) => { + entry.insert(slot); + } + hash_map::Entry::Occupied(mut entry) => { + let value = entry.get_mut(); + // if new value is same as original value. Remove storage entry. + if value.original_value() == slot.present_value() { + entry.remove(); + } else { + // if value is different, update transition present value; + value.present_value = slot.present_value; + } + } + } + } + } + } + *) + Definition update (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "info" + |), + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::transition_account::TransitionAccount", + "info" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "status" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::transition_account::TransitionAccount", + "status" + |) + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.match_operator (| + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::transition_account::TransitionAccount", + "status" + |), + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::Destroyed" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm::db::states::account_status::AccountStatus::DestroyedAgain" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => M.alloc (| Value.Bool true |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::transition_account::TransitionAccount", + "storage" + |) + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage_was_destroyed" + |), + Value.Bool true + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "into_iter", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + other, + "revm::db::states::transition_account::TransitionAccount", + "storage" + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IntoIter") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := + M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let key := M.copy (| ฮณ1_0 |) in + let slot := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage" + |); + M.read (| key |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.read (| slot |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ value := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + "get_mut", + [] + |), + [ entry ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::StorageSlot", + "original_value", + [] + |), + [ M.read (| value |) ] + |) + |); + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::StorageSlot", + "present_value", + [] + |), + [ slot ] + |) + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + "remove", + [] + |), + [ M.read (| entry |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| value |), + "revm_primitives::state::StorageSlot", + "present_value" + |), + M.read (| + M.SubPointer.get_struct_record_field (| + slot, + "revm_primitives::state::StorageSlot", + "present_value" + |) + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_update : M.IsAssociatedFunction Self "update" update. + + (* + pub fn create_revert(self) -> Option { + let mut previous_account = self.original_bundle_account(); + previous_account.update_and_create_revert(self) + } + *) + Definition create_revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ previous_account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::transition_account::TransitionAccount", + "original_bundle_account", + [] + |), + [ self ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::db::states::bundle_account::BundleAccount", + "update_and_create_revert", + [] + |), + [ previous_account; M.read (| self |) ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_create_revert : + M.IsAssociatedFunction Self "create_revert" create_revert. + + (* + pub fn present_bundle_account(&self) -> BundleAccount { + BundleAccount { + info: self.info.clone(), + original_info: self.previous_info.clone(), + storage: self.storage.clone(), + status: self.status, + } + } + *) + Definition present_bundle_account (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::bundle_account::BundleAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "info" + |) + ] + |)); + ("original_info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_info" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "storage" + |) + ] + |)); + ("status", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "status" + |) + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_present_bundle_account : + M.IsAssociatedFunction Self "present_bundle_account" present_bundle_account. + + (* + fn original_bundle_account(&self) -> BundleAccount { + BundleAccount { + info: self.previous_info.clone(), + original_info: self.previous_info.clone(), + storage: StorageWithOriginalValues::new(), + status: self.previous_status, + } + } + *) + Definition original_bundle_account (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::bundle_account::BundleAccount" + [ + ("info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_info" + |) + ] + |)); + ("original_info", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_info" + |) + ] + |)); + ("storage", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("status", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_account::TransitionAccount", + "previous_status" + |) + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_original_bundle_account : + M.IsAssociatedFunction Self "original_bundle_account" original_bundle_account. + End Impl_revm_db_states_transition_account_TransitionAccount. + End transition_account. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/transition_state.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/transition_state.md new file mode 100644 index 00000000..1fa48f64 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/db/states/transition_state.md @@ -0,0 +1,557 @@ +# ๐Ÿ“ transition_state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/db/states/transition_state.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module db. + Module states. + Module transition_state. + (* StructRecord + { + name := "TransitionState"; + ty_params := []; + fields := + [ + ("transitions", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ]) + ]; + } *) + + Module Impl_core_clone_Clone_for_revm_db_states_transition_state_TransitionState. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_state::TransitionState". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::db::states::transition_state::TransitionState" + [ + ("transitions", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_state::TransitionState", + "transitions" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_db_states_transition_state_TransitionState. + + Module Impl_core_default_Default_for_revm_db_states_transition_state_TransitionState. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_state::TransitionState". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::db::states::transition_state::TransitionState" + [ + ("transitions", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_db_states_transition_state_TransitionState. + + Module Impl_core_fmt_Debug_for_revm_db_states_transition_state_TransitionState. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_state::TransitionState". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "TransitionState" |); + M.read (| Value.String "transitions" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_state::TransitionState", + "transitions" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_db_states_transition_state_TransitionState. + + Module Impl_core_marker_StructuralPartialEq_for_revm_db_states_transition_state_TransitionState. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_state::TransitionState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_db_states_transition_state_TransitionState. + + Module Impl_core_cmp_PartialEq_for_revm_db_states_transition_state_TransitionState. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_state::TransitionState". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_state::TransitionState", + "transitions" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::db::states::transition_state::TransitionState", + "transitions" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_db_states_transition_state_TransitionState. + + Module Impl_core_marker_StructuralEq_for_revm_db_states_transition_state_TransitionState. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_state::TransitionState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_db_states_transition_state_TransitionState. + + Module Impl_core_cmp_Eq_for_revm_db_states_transition_state_TransitionState. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_state::TransitionState". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_db_states_transition_state_TransitionState. + + Module Impl_revm_db_states_transition_state_TransitionState. + Definition Self : Ty.t := Ty.path "revm::db::states::transition_state::TransitionState". + + (* + pub fn single(address: Address, transition: TransitionAccount) -> Self { + let mut transitions = HashMap::new(); + transitions.insert(address, transition); + TransitionState { transitions } + } + *) + Definition single (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ address; transition ] => + ltac:(M.monadic + (let address := M.alloc (| address |) in + let transition := M.alloc (| transition |) in + M.read (| + let~ transitions := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ transitions; M.read (| address |); M.read (| transition |) ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::db::states::transition_state::TransitionState" + [ ("transitions", M.read (| transitions |)) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_single : M.IsAssociatedFunction Self "single" single. + + (* + pub fn take(&mut self) -> TransitionState { + core::mem::take(self) + } + *) + Definition take (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_function (| + "core::mem::take", + [ Ty.path "revm::db::states::transition_state::TransitionState" ] + |), + [ M.read (| self |) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_take : M.IsAssociatedFunction Self "take" take. + + (* + pub fn add_transitions(&mut self, transitions: Vec<(Address, TransitionAccount)>) { + for (address, account) in transitions { + match self.transitions.entry(address) { + Entry::Occupied(entry) => { + let entry = entry.into_mut(); + entry.update(account); + } + Entry::Vacant(entry) => { + entry.insert(account); + } + } + } + } + *) + Definition add_transitions (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; transitions ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let transitions := M.alloc (| transitions |) in + M.read (| + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm::db::states::transition_account::TransitionAccount" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| transitions |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ1_0 := M.SubPointer.get_tuple_field (| ฮณ0_0, 0 |) in + let ฮณ1_1 := M.SubPointer.get_tuple_field (| ฮณ0_0, 1 |) in + let address := M.copy (| ฮณ1_0 |) in + let account := M.copy (| ฮณ1_1 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::db::states::transition_state::TransitionState", + "transitions" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ entry := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::OccupiedEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ], + "into_mut", + [] + |), + [ M.read (| entry |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm::db::states::transition_account::TransitionAccount", + "update", + [] + |), + [ M.read (| entry |); M.read (| account |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm::db::states::transition_account::TransitionAccount" + ], + "insert", + [] + |), + [ M.read (| entry |); M.read (| account |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_add_transitions : + M.IsAssociatedFunction Self "add_transitions" add_transitions. + End Impl_revm_db_states_transition_state_TransitionState. + End transition_state. + End states. +End db. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/evm.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/evm.md new file mode 100644 index 00000000..09025893 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/evm.md @@ -0,0 +1,6499 @@ +# ๐Ÿ“ evm.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/evm.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module evm. + Definition value_CALL_STACK_LIMIT : Value.t := + M.run ltac:(M.monadic (M.alloc (| Value.Integer 1024 |))). + + (* StructRecord + { + name := "Evm"; + ty_params := [ "EXT"; "DB" ]; + fields := + [ + ("context", Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ]); + ("handler", + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ]) + ]; + } *) + + Module Impl_core_fmt_Debug_where_core_fmt_Debug_EXT_where_revm_primitives_db_Database_DB_where_core_fmt_Debug_DB_where_core_fmt_Debug_associated_type_for_revm_evm_Evm_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]. + + (* + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Evm") + .field("evm context", &self.context.evm) + .finish_non_exhaustive() + } + *) + Definition fmt (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "finish_non_exhaustive", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::builders::DebugStruct", + "field", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct", + [] + |), + [ M.read (| f |); M.read (| Value.String "Evm" |) ] + |) + |); + M.read (| Value.String "evm context" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (EXT DB : Ty.t), + M.IsTraitInstance + "core::fmt::Debug" + (Self EXT DB) + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method (fmt EXT DB)) ]. + End Impl_core_fmt_Debug_where_core_fmt_Debug_EXT_where_revm_primitives_db_Database_DB_where_core_fmt_Debug_DB_where_core_fmt_Debug_associated_type_for_revm_evm_Evm_EXT_DB. + + Module Impl_revm_evm_Evm_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]. + + (* + pub fn transact_commit(&mut self) -> Result> { + let ResultAndState { result, state } = self.transact()?; + self.context.evm.db.commit(state); + Ok(result) + } + *) + Definition transact_commit (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "transact", + [] + |), + [ M.read (| self |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ExecutionResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ResultAndState", + "result" + |) in + let ฮณ0_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_primitives::result::ResultAndState", + "state" + |) in + let result := M.copy (| ฮณ0_0 |) in + let state := M.copy (| ฮณ0_1 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::DatabaseCommit", + DB, + [], + "commit", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |); + M.read (| state |) + ] + |) + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ M.read (| result |) ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transact_commit : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "transact_commit" (transact_commit EXT DB). + (* + pub fn new( + mut context: Context, + handler: Handler<'a, Self, EXT, DB>, + ) -> Evm<'a, EXT, DB> { + context.evm.journaled_state.set_spec_id(handler.cfg.spec_id); + Evm { context, handler } + } + *) + Definition new (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ context; handler ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let handler := M.alloc (| handler |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "set_spec_id", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + context, + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + handler, + "revm::handler::Handler", + "cfg" + |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |) + |) + ] + |) + |) in + M.alloc (| + Value.StructRecord + "revm::evm::Evm" + [ ("context", M.read (| context |)); ("handler", M.read (| handler |)) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "new" (new EXT DB). + + (* + pub fn modify(self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + EvmBuilder::new(self) + } + *) + Definition modify (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ Ty.path "revm::builder::HandlerStage"; EXT; DB ], + "new", + [] + |), + [ M.read (| self |) ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_modify : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "modify" (modify EXT DB). + (* + pub fn spec_id(&self) -> SpecId { + self.handler.cfg.spec_id + } + *) + Definition spec_id (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |), + "revm::handler::Handler", + "cfg" + |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_spec_id : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "spec_id" (spec_id EXT DB). + + (* + pub fn preverify_transaction(&mut self) -> Result<(), EVMError> { + let output = self.preverify_transaction_inner().map(|_| ()); + self.clear(); + output + } + *) + Definition preverify_transaction (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ output := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map", + [ Ty.tuple []; Ty.function [ Ty.tuple [ Ty.path "u64" ] ] (Ty.tuple []) ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "preverify_transaction_inner", + [] + |), + [ M.read (| self |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ fun ฮณ => ltac:(M.monadic (Value.Tuple [])) ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "clear", + [] + |), + [ M.read (| self |) ] + |) + |) in + output + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_preverify_transaction : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "preverify_transaction" (preverify_transaction EXT DB). + + (* + fn clear(&mut self) { + self.handler.post_execution().clear(&mut self.context); + } + *) + Definition clear (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::handle_types::post_execution::PostExecutionHandler") + [ EXT; DB ], + "clear", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "post_execution", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_clear : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "clear" (clear EXT DB). + + (* + pub fn transact_preverified(&mut self) -> EVMResult { + let initial_gas_spend = self + .handler + .validation() + .initial_tx_gas(&self.context.evm.env) + .map_err(|e| { + self.clear(); + e + })?; + let output = self.transact_preverified_inner(initial_gas_spend); + let output = self.handler.post_execution().end(&mut self.context, output); + self.clear(); + output + } + *) + Definition transact_preverified (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ initial_gas_spend := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ] + (Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::validation::ValidationHandler") + [ EXT; DB ], + "initial_tx_gas", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB + ], + "validation", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::evm::Evm") + [ EXT; DB ], + "clear", + [] + |), + [ M.read (| self |) ] + |) + |) in + e + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ output := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "transact_preverified_inner", + [] + |), + [ M.read (| self |); M.read (| initial_gas_spend |) ] + |) + |) in + let~ output := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::post_execution::PostExecutionHandler") + [ EXT; DB ], + "end", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "post_execution", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |); + M.read (| output |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "clear", + [] + |), + [ M.read (| self |) ] + |) + |) in + output + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transact_preverified : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "transact_preverified" (transact_preverified EXT DB). + + (* + fn preverify_transaction_inner(&mut self) -> Result> { + self.handler.validation().env(&self.context.evm.env)?; + let initial_gas_spend = self + .handler + .validation() + .initial_tx_gas(&self.context.evm.env)?; + self.handler + .validation() + .tx_against_state(&mut self.context)?; + Ok(initial_gas_spend) + } + *) + Definition preverify_transaction_inner (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::validation::ValidationHandler") + [ EXT; DB ], + "env", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "validation", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ initial_gas_spend := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::validation::ValidationHandler") + [ EXT; DB ], + "initial_tx_gas", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "validation", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::validation::ValidationHandler") + [ EXT; DB ], + "tx_against_state", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "validation", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ M.read (| initial_gas_spend |) ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_preverify_transaction_inner : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "preverify_transaction_inner" + (preverify_transaction_inner EXT DB). + + (* + pub fn transact(&mut self) -> EVMResult { + let initial_gas_spend = self.preverify_transaction_inner().map_err(|e| { + self.clear(); + e + })?; + + let output = self.transact_preverified_inner(initial_gas_spend); + let output = self.handler.post_execution().end(&mut self.context, output); + self.clear(); + output + } + *) + Definition transact (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ initial_gas_spend := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ] + (Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "preverify_transaction_inner", + [] + |), + [ M.read (| self |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::evm::Evm") + [ EXT; DB ], + "clear", + [] + |), + [ M.read (| self |) ] + |) + |) in + e + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ output := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "transact_preverified_inner", + [] + |), + [ M.read (| self |); M.read (| initial_gas_spend |) ] + |) + |) in + let~ output := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::post_execution::PostExecutionHandler") + [ EXT; DB ], + "end", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "post_execution", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |); + M.read (| output |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "clear", + [] + |), + [ M.read (| self |) ] + |) + |) in + output + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transact : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "transact" (transact EXT DB). + + (* + pub fn handler_cfg(&self) -> &HandlerCfg { + &self.handler.cfg + } + *) + Definition handler_cfg (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |), + "revm::handler::Handler", + "cfg" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_handler_cfg : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "handler_cfg" (handler_cfg EXT DB). + + (* + pub fn cfg(&self) -> &CfgEnv { + &self.env().cfg + } + *) + Definition cfg (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "revm_interpreter::host::Host", + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + [], + "env", + [] + |), + [ M.read (| self |) ] + |), + "revm_primitives::env::Env", + "cfg" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_cfg : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "cfg" (cfg EXT DB). + + (* + pub fn cfg_mut(&mut self) -> &mut CfgEnv { + &mut self.context.evm.env.cfg + } + *) + Definition cfg_mut (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "cfg" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_cfg_mut : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "cfg_mut" (cfg_mut EXT DB). + + (* + pub fn tx(&self) -> &TxEnv { + &self.context.evm.env.tx + } + *) + Definition tx (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_tx : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "tx" (tx EXT DB). + + (* + pub fn tx_mut(&mut self) -> &mut TxEnv { + &mut self.context.evm.env.tx + } + *) + Definition tx_mut (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_tx_mut : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "tx_mut" (tx_mut EXT DB). + + (* + pub fn db(&self) -> &DB { + &self.context.evm.db + } + *) + Definition db (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_db : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "db" (db EXT DB). + + (* + pub fn db_mut(&mut self) -> &mut DB { + &mut self.context.evm.db + } + *) + Definition db_mut (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_db_mut : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "db_mut" (db_mut EXT DB). + + (* + pub fn block(&self) -> &BlockEnv { + &self.context.evm.env.block + } + *) + Definition block (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "block" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_block : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "block" (block EXT DB). + + (* + pub fn block_mut(&mut self) -> &mut BlockEnv { + &mut self.context.evm.env.block + } + *) + Definition block_mut (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "block" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_block_mut : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "block_mut" (block_mut EXT DB). + + (* + pub fn modify_spec_id(&mut self, spec_id: SpecId) { + self.handler.modify_spec_id(spec_id); + } + *) + Definition modify_spec_id (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; spec_id ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let spec_id := M.alloc (| spec_id |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "modify_spec_id", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |); + M.read (| spec_id |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_modify_spec_id : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "modify_spec_id" (modify_spec_id EXT DB). + + (* + pub fn into_context(self) -> Context { + self.context + } + *) + Definition into_context (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| self, "revm::evm::Evm", "context" |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_context : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "into_context" (into_context EXT DB). + + (* + pub fn into_db_and_env_with_handler_cfg(self) -> (DB, EnvWithHandlerCfg) { + ( + self.context.evm.inner.db, + EnvWithHandlerCfg { + env: self.context.evm.inner.env, + handler_cfg: self.handler.cfg, + }, + ) + } + *) + Definition into_db_and_env_with_handler_cfg + (EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| self, "revm::evm::Evm", "context" |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + |); + Value.StructRecord + "revm_primitives::env::handler_cfg::EnvWithHandlerCfg" + [ + ("env", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |)); + ("handler_cfg", + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + self, + "revm::evm::Evm", + "handler" + |), + "revm::handler::Handler", + "cfg" + |) + |)) + ] + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_db_and_env_with_handler_cfg : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "into_db_and_env_with_handler_cfg" + (into_db_and_env_with_handler_cfg EXT DB). + + (* + pub fn into_context_with_handler_cfg(self) -> ContextWithHandlerCfg { + ContextWithHandlerCfg::new(self.context, self.handler.cfg) + } + *) + Definition into_context_with_handler_cfg + (EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::ContextWithHandlerCfg") [ EXT; DB ], + "new", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| self, "revm::evm::Evm", "context" |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| self, "revm::evm::Evm", "handler" |), + "revm::handler::Handler", + "cfg" + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_context_with_handler_cfg : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "into_context_with_handler_cfg" + (into_context_with_handler_cfg EXT DB). + + (* + pub fn start_the_loop( + &mut self, + first_frame: Frame, + ) -> Result> { + // take instruction table + let table = self + .handler + .take_instruction_table() + .expect("Instruction table should be present"); + + // run main loop + let frame_result = match &table { + InstructionTables::Plain(table) => self.run_the_loop(table, first_frame), + InstructionTables::Boxed(table) => self.run_the_loop(table, first_frame), + }; + + // return back instruction table + self.handler.set_instruction_table(table); + + frame_result + } + *) + Definition start_the_loop (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; first_frame ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let first_frame := M.alloc (| first_frame |) in + M.read (| + let~ table := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "revm_interpreter::opcode::InstructionTables") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "take_instruction_table", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |); + M.read (| Value.String "Instruction table should be present" |) + ] + |) + |) in + let~ frame_result := + M.copy (| + M.match_operator (| + M.alloc (| table |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Plain", + 0 + |) in + let table := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "run_the_loop", + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::Interpreter" ]; + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + ] + (Ty.tuple []) + ] + |), + [ M.read (| self |); M.read (| table |); M.read (| first_frame |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Boxed", + 0 + |) in + let table := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "run_the_loop", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ M.read (| self |); M.read (| table |); M.read (| first_frame |) ] + |) + |))) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "set_instruction_table", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |); + M.read (| table |) + ] + |) + |) in + frame_result + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_start_the_loop : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "start_the_loop" (start_the_loop EXT DB). + + (* + pub fn run_the_loop( + &mut self, + instruction_table: &[FN; 256], + first_frame: Frame, + ) -> Result> + where + FN: Fn(&mut Interpreter, &mut Self), + { + let mut call_stack: Vec = Vec::with_capacity(1025); + call_stack.push(first_frame); + + #[cfg(feature = "memory_limit")] + let mut shared_memory = + SharedMemory::new_with_memory_limit(self.context.evm.env.cfg.memory_limit); + #[cfg(not(feature = "memory_limit"))] + let mut shared_memory = SharedMemory::new(); + + shared_memory.new_context(); + + // peek last stack frame. + let mut stack_frame = call_stack.last_mut().unwrap(); + + loop { + // run interpreter + let interpreter = &mut stack_frame.frame_data_mut().interpreter; + let next_action = interpreter.run(shared_memory, instruction_table, self); + + // take error and break the loop if there is any. + // This error is set From Interpreter when it's interacting with Host. + self.context.evm.take_error()?; + // take shared memory back. + shared_memory = interpreter.take_memory(); + + let exec = &mut self.handler.execution; + let frame_or_result = match next_action { + InterpreterAction::Call { inputs } => exec.call(&mut self.context, inputs)?, + InterpreterAction::Create { inputs } => exec.create(&mut self.context, inputs)?, + InterpreterAction::EOFCreate { inputs } => { + exec.eofcreate(&mut self.context, inputs)? + } + InterpreterAction::Return { result } => { + // free memory context. + shared_memory.free_context(); + + // pop last frame from the stack and consume it to create FrameResult. + let returned_frame = call_stack + .pop() + .expect("We just returned from Interpreter frame"); + + let ctx = &mut self.context; + FrameOrResult::Result(match returned_frame { + Frame::Call(frame) => { + // return_call + FrameResult::Call(exec.call_return(ctx, frame, result)?) + } + Frame::Create(frame) => { + // return_create + FrameResult::Create(exec.create_return(ctx, frame, result)?) + } + Frame::EOFCreate(frame) => { + // return_eofcreate + FrameResult::EOFCreate(exec.eofcreate_return(ctx, frame, result)?) + } + }) + } + InterpreterAction::None => unreachable!("InterpreterAction::None is not expected"), + }; + + // handle result + match frame_or_result { + FrameOrResult::Frame(frame) => { + shared_memory.new_context(); + call_stack.push(frame); + stack_frame = call_stack.last_mut().unwrap(); + } + FrameOrResult::Result(result) => { + let Some(top_frame) = call_stack.last_mut() else { + // Break the look if there are no more frames. + return Ok(result); + }; + stack_frame = top_frame; + let ctx = &mut self.context; + // Insert result to the top frame. + match result { + FrameResult::Call(outcome) => { + // return_call + exec.insert_call_outcome(ctx, stack_frame, &mut shared_memory, outcome)? + } + FrameResult::Create(outcome) => { + // return_create + exec.insert_create_outcome(ctx, stack_frame, outcome)? + } + FrameResult::EOFCreate(outcome) => { + // return_eofcreate + exec.insert_eofcreate_outcome(ctx, stack_frame, outcome)? + } + } + } + } + } + } + *) + Definition run_the_loop (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ FN ], [ self; instruction_table; first_frame ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let instruction_table := M.alloc (| instruction_table |) in + let first_frame := M.alloc (| first_frame |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ call_stack := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "revm::frame::Frame"; Ty.path "alloc::alloc::Global" ], + "with_capacity", + [] + |), + [ Value.Integer 1025 ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "revm::frame::Frame"; Ty.path "alloc::alloc::Global" ], + "push", + [] + |), + [ call_stack; M.read (| first_frame |) ] + |) + |) in + let~ shared_memory := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "new", + [] + |), + [] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "new_context", + [] + |), + [ shared_memory ] + |) + |) in + let~ stack_frame := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::Frame" ] ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "slice") [ Ty.path "revm::frame::Frame" ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "revm::frame::Frame"; Ty.path "alloc::alloc::Global" ], + [], + "deref_mut", + [] + |), + [ call_stack ] + |) + ] + |) + ] + |) + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.loop (| + ltac:(M.monadic + (let~ interpreter := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::Frame", + "frame_data_mut", + [] + |), + [ M.read (| stack_frame |) ] + |), + "revm::frame::FrameData", + "interpreter" + |) + |) in + let~ next_action := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "run", + [ FN; Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + |), + [ + M.read (| interpreter |); + M.read (| shared_memory |); + M.read (| instruction_table |); + M.read (| self |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::context::inner_evm_context::InnerEvmContext") + [ DB ], + "take_error", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ _ := + M.write (| + shared_memory, + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "take_memory", + [] + |), + [ M.read (| interpreter |) ] + |) + |) in + let~ exec := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |), + "revm::handler::Handler", + "execution" + |) + |) in + let~ frame_or_result := + M.copy (| + M.match_operator (| + next_action, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Call", + "inputs" + |) in + let inputs := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "call", + [] + |), + [ + M.read (| exec |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |); + M.read (| inputs |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Create", + "inputs" + |) in + let inputs := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "create", + [] + |), + [ + M.read (| exec |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |); + M.read (| inputs |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate", + "inputs" + |) in + let inputs := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "eofcreate", + [] + |), + [ + M.read (| exec |); + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |); + M.read (| inputs |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::Return", + "result" + |) in + let result := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "free_context", + [] + |), + [ shared_memory ] + |) + |) in + let~ returned_frame := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm::frame::Frame" ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::frame::Frame"; + Ty.path "alloc::alloc::Global" + ], + "pop", + [] + |), + [ call_stack ] + |); + M.read (| + Value.String + "We just returned from Interpreter frame" + |) + ] + |) + |) in + let~ ctx := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |) + |) in + M.alloc (| + Value.StructTuple + "revm::frame::FrameOrResult::Result" + [ + M.read (| + M.match_operator (| + returned_frame, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::Call", + 0 + |) in + let frame := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "revm::frame::FrameResult::Call" + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "call_return", + [] + |), + [ + M.read (| exec |); + M.read (| ctx |); + M.read (| frame |); + M.read (| result |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := + M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm::frame::FrameResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ + Ty.associated + ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ + Ty.associated + ] + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::Create", + 0 + |) in + let frame := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "revm::frame::FrameResult::Create" + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "create_return", + [] + |), + [ + M.read (| exec |); + M.read (| ctx |); + M.read (| frame |); + M.read (| result |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := + M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm::frame::FrameResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ + Ty.associated + ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ + Ty.associated + ] + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::EOFCreate", + 0 + |) in + let frame := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructTuple + "revm::frame::FrameResult::EOFCreate" + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "eofcreate_return", + [] + |), + [ + M.read (| exec |); + M.read (| ctx |); + M.read (| frame |); + M.read (| result |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := + M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm::frame::FrameResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ + Ty.associated + ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ + Ty.associated + ] + ] + ], + "from_residual", + [] + |), + [ + M.read (| + residual + |) + ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := + M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) + ] + |))) + ] + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::interpreter_action::InterpreterAction::None" + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "internal error: entered unreachable code: InterpreterAction::None is not expected" + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "none", + [] + |), + [] + |) + |)) + ] + |) + ] + |) + |) + |))) + ] + |) + |) in + M.match_operator (| + frame_or_result, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameOrResult::Frame", + 0 + |) in + let frame := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory", + "new_context", + [] + |), + [ shared_memory ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::frame::Frame"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ call_stack; M.read (| frame |) ] + |) + |) in + let~ _ := + M.write (| + stack_frame, + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm::frame::Frame" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "revm::frame::Frame" ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::frame::Frame"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ call_stack ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameOrResult::Result", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ Ty.path "revm::frame::Frame" ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::frame::Frame"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ call_stack ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let top_frame := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| stack_frame, M.read (| top_frame |) |) in + let~ ctx := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |) + |) in + M.match_operator (| + result, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Call", + 0 + |) in + let outcome := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "insert_call_outcome", + [] + |), + [ + M.read (| exec |); + M.read (| ctx |); + M.read (| stack_frame |); + shared_memory; + M.read (| outcome |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm::frame::FrameResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Create", + 0 + |) in + let outcome := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "insert_create_outcome", + [] + |), + [ + M.read (| exec |); + M.read (| ctx |); + M.read (| stack_frame |); + M.read (| outcome |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm::frame::FrameResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::EOFCreate", + 0 + |) in + let outcome := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "insert_eofcreate_outcome", + [] + |), + [ + M.read (| exec |); + M.read (| ctx |); + M.read (| stack_frame |); + M.read (| outcome |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "revm::frame::FrameResult"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + |) + |) + |) + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_run_the_loop : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "run_the_loop" (run_the_loop EXT DB). + + (* + fn transact_preverified_inner(&mut self, initial_gas_spend: u64) -> EVMResult { + let ctx = &mut self.context; + let pre_exec = self.handler.pre_execution(); + + // load access list and beneficiary if needed. + pre_exec.load_accounts(ctx)?; + + // load precompiles + let precompiles = pre_exec.load_precompiles(); + ctx.evm.set_precompiles(precompiles); + + // deduce caller balance with its limit. + pre_exec.deduct_caller(ctx)?; + + let gas_limit = ctx.evm.env.tx.gas_limit - initial_gas_spend; + + let exec = self.handler.execution(); + // call inner handling of call/create + let first_frame_or_result = match ctx.evm.env.tx.transact_to { + TransactTo::Call(_) => exec.call( + ctx, + CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + )?, + TransactTo::Create => exec.create( + ctx, + CreateInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + )?, + }; + + // Starts the main running loop. + let mut result = match first_frame_or_result { + FrameOrResult::Frame(first_frame) => self.start_the_loop(first_frame)?, + FrameOrResult::Result(result) => result, + }; + + let ctx = &mut self.context; + + // handle output of call/create calls. + self.handler + .execution() + .last_frame_return(ctx, &mut result)?; + + let post_exec = self.handler.post_execution(); + // Reimburse the caller + post_exec.reimburse_caller(ctx, result.gas())?; + // Reward beneficiary + post_exec.reward_beneficiary(ctx, result.gas())?; + // Returns output of transaction. + post_exec.output(ctx, result) + } + *) + Definition transact_preverified_inner (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; initial_gas_spend ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let initial_gas_spend := M.alloc (| initial_gas_spend |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ ctx := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |) + |) in + let~ pre_exec := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "pre_execution", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::pre_execution::PreExecutionHandler") + [ EXT; DB ], + "load_accounts", + [] + |), + [ M.read (| pre_exec |); M.read (| ctx |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ precompiles := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::pre_execution::PreExecutionHandler") + [ EXT; DB ], + "load_precompiles", + [] + |), + [ M.read (| pre_exec |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + "set_precompiles", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |); + M.read (| precompiles |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::pre_execution::PreExecutionHandler") + [ EXT; DB ], + "deduct_caller", + [] + |), + [ M.read (| pre_exec |); M.read (| ctx |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ gas_limit := + M.alloc (| + BinOp.Wrap.sub + Integer.U64 + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_limit" + |) + |)) + (M.read (| initial_gas_spend |)) + |) in + let~ exec := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "execution", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |) + |) in + let~ first_frame_or_result := + M.copy (| + M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "transact_to" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "call", + [] + |), + [ + M.read (| exec |); + M.read (| ctx |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "new_boxed", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |); + M.read (| gas_limit |) + ] + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::env::TransactTo::Create" + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "create", + [] + |), + [ + M.read (| exec |); + M.read (| ctx |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "new_boxed", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |); + M.read (| gas_limit |) + ] + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))) + ] + |) + |) in + let~ result := + M.copy (| + M.match_operator (| + first_frame_or_result, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameOrResult::Frame", + 0 + |) in + let first_frame := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ], + "start_the_loop", + [] + |), + [ M.read (| self |); M.read (| first_frame |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameOrResult::Result", + 0 + |) in + let result := M.copy (| ฮณ0_0 |) in + result)) + ] + |) + |) in + let~ ctx := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "last_frame_return", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "execution", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |); + M.read (| ctx |); + result + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ post_exec := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "post_execution", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "handler" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::post_execution::PostExecutionHandler") + [ EXT; DB ], + "reimburse_caller", + [] + |), + [ + M.read (| post_exec |); + M.read (| ctx |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameResult", + "gas", + [] + |), + [ result ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::post_execution::PostExecutionHandler") + [ EXT; DB ], + "reward_beneficiary", + [] + |), + [ + M.read (| post_exec |); + M.read (| ctx |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameResult", + "gas", + [] + |), + [ result ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "revm::handler::handle_types::post_execution::PostExecutionHandler") + [ EXT; DB ], + "output", + [] + |), + [ M.read (| post_exec |); M.read (| ctx |); M.read (| result |) ] + |) + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transact_preverified_inner : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "transact_preverified_inner" + (transact_preverified_inner EXT DB). + End Impl_revm_evm_Evm_EXT_DB. + + Module Impl_revm_evm_Evm_Tuple__revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + Definition Self : Ty.t := + Ty.apply + (Ty.path "revm::evm::Evm") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ]. + + (* + pub fn builder() -> EvmBuilder<'a, SetGenericStage, (), EmptyDB> { + EvmBuilder::default() + } + *) + Definition builder (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "revm::builder::EvmBuilder") + [ + Ty.path "revm::builder::SetGenericStage"; + Ty.tuple []; + Ty.apply + (Ty.path "revm::db::emptydb::EmptyDBTyped") + [ Ty.path "core::convert::Infallible" ] + ], + [], + "default", + [] + |), + [] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_builder : M.IsAssociatedFunction Self "builder" builder. + End Impl_revm_evm_Evm_Tuple__revm_db_emptydb_EmptyDBTyped_core_convert_Infallible. + + + + Module Impl_revm_interpreter_host_Host_where_revm_primitives_db_Database_DB_for_revm_evm_Evm_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]. + + (* + fn env(&self) -> &Env { + &self.context.evm.env + } + *) + Definition env (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |))) + | _, _ => M.impossible + end. + + (* + fn env_mut(&mut self) -> &mut Env { + &mut self.context.evm.env + } + *) + Definition env_mut (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |))) + | _, _ => M.impossible + end. + + (* + fn block_hash(&mut self, number: U256) -> Option { + self.context + .evm + .block_hash(number) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + *) + Definition block_hash (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; number ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let number := M.alloc (| number |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes"; Ty.tuple [] ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "alloy_primitives::bits::fixed::FixedBytes"; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map_err", + [ + Ty.tuple []; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "block_hash", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| number |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |), + Value.StructTuple + "core::result::Result::Err" + [ M.read (| e |) ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn load_account(&mut self, address: Address) -> Option { + self.context + .evm + .load_account_exist(address) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + *) + Definition load_account (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "revm_interpreter::host::LoadAccountResult"; Ty.tuple [] ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_interpreter::host::LoadAccountResult"; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map_err", + [ + Ty.tuple []; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "load_account_exist", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| address |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |), + Value.StructTuple + "core::result::Result::Err" + [ M.read (| e |) ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn balance(&mut self, address: Address) -> Option<(U256, bool)> { + self.context + .evm + .balance(address) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + *) + Definition balance (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "bool" ]; Ty.tuple [] ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "bool" ]; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map_err", + [ + Ty.tuple []; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "balance", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| address |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |), + Value.StructTuple + "core::result::Result::Err" + [ M.read (| e |) ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn code(&mut self, address: Address) -> Option<(Bytecode, bool)> { + self.context + .evm + .code(address) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + *) + Definition code (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "revm_primitives::bytecode::Bytecode"; Ty.path "bool" ]; + Ty.tuple [] + ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "revm_primitives::bytecode::Bytecode"; Ty.path "bool" ]; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map_err", + [ + Ty.tuple []; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "code", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| address |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |), + Value.StructTuple + "core::result::Result::Err" + [ M.read (| e |) ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn code_hash(&mut self, address: Address) -> Option<(B256, bool)> { + self.context + .evm + .code_hash(address) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + *) + Definition code_hash (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "alloy_primitives::bits::fixed::FixedBytes"; Ty.path "bool" ]; + Ty.tuple [] + ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes"; Ty.path "bool" ]; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map_err", + [ + Ty.tuple []; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "code_hash", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| address |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |), + Value.StructTuple + "core::result::Result::Err" + [ M.read (| e |) ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn sload(&mut self, address: Address, index: U256) -> Option<(U256, bool)> { + self.context + .evm + .sload(address, index) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + *) + Definition sload (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "bool" ]; Ty.tuple [] ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "bool" ]; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map_err", + [ + Ty.tuple []; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "sload", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| address |); + M.read (| index |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |), + Value.StructTuple + "core::result::Result::Err" + [ M.read (| e |) ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn sstore(&mut self, address: Address, index: U256, value: U256) -> Option { + self.context + .evm + .sstore(address, index, value) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + *) + Definition sstore (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; address; index; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + let value := M.alloc (| value |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "revm_interpreter::host::SStoreResult"; Ty.tuple [] ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_interpreter::host::SStoreResult"; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map_err", + [ + Ty.tuple []; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "sstore", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| address |); + M.read (| index |); + M.read (| value |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |), + Value.StructTuple + "core::result::Result::Err" + [ M.read (| e |) ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn tload(&mut self, address: Address, index: U256) -> U256 { + self.context.evm.tload(address, index) + } + *) + Definition tload (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; address; index ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "tload", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| address |); + M.read (| index |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn tstore(&mut self, address: Address, index: U256, value: U256) { + self.context.evm.tstore(address, index, value) + } + *) + Definition tstore (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; address; index; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let index := M.alloc (| index |) in + let value := M.alloc (| value |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "tstore", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| address |); + M.read (| index |); + M.read (| value |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn log(&mut self, log: Log) { + self.context.evm.journaled_state.log(log); + } + *) + Definition log (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; log ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let log := M.alloc (| log |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "log", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| log |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn selfdestruct(&mut self, address: Address, target: Address) -> Option { + self.context + .evm + .inner + .journaled_state + .selfdestruct(address, target, &mut self.context.evm.inner.db) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + *) + Definition selfdestruct (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; address; target ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let target := M.alloc (| target |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "revm_interpreter::host::SelfDestructResult"; Ty.tuple [] ], + "ok", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_interpreter::host::SelfDestructResult"; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ], + "map_err", + [ + Ty.tuple []; + Ty.function + [ + Ty.tuple + [ Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "selfdestruct", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| address |); + M.read (| target |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let e := M.copy (| ฮณ |) in + M.read (| + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |), + Value.StructTuple + "core::result::Result::Err" + [ M.read (| e |) ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (EXT DB : Ty.t), + M.IsTraitInstance + "revm_interpreter::host::Host" + (Self EXT DB) + (* Trait polymorphic types *) [] + (* Instance *) + [ + ("env", InstanceField.Method (env EXT DB)); + ("env_mut", InstanceField.Method (env_mut EXT DB)); + ("block_hash", InstanceField.Method (block_hash EXT DB)); + ("load_account", InstanceField.Method (load_account EXT DB)); + ("balance", InstanceField.Method (balance EXT DB)); + ("code", InstanceField.Method (code EXT DB)); + ("code_hash", InstanceField.Method (code_hash EXT DB)); + ("sload", InstanceField.Method (sload EXT DB)); + ("sstore", InstanceField.Method (sstore EXT DB)); + ("tload", InstanceField.Method (tload EXT DB)); + ("tstore", InstanceField.Method (tstore EXT DB)); + ("log", InstanceField.Method (log EXT DB)); + ("selfdestruct", InstanceField.Method (selfdestruct EXT DB)) + ]. + End Impl_revm_interpreter_host_Host_where_revm_primitives_db_Database_DB_for_revm_evm_Evm_EXT_DB. +End evm. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/frame.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/frame.md new file mode 100644 index 00000000..59307aad --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/frame.md @@ -0,0 +1,1764 @@ +# ๐Ÿ“ frame.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/frame.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module frame. + (* StructRecord + { + name := "CallFrame"; + ty_params := []; + fields := + [ + ("return_memory_range", Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ]); + ("frame_data", Ty.path "revm::frame::FrameData") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_frame_CallFrame. + Definition Self : Ty.t := Ty.path "revm::frame::CallFrame". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CallFrame" |); + M.read (| Value.String "return_memory_range" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::frame::CallFrame", + "return_memory_range" + |)); + M.read (| Value.String "frame_data" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::frame::CallFrame", + "frame_data" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_frame_CallFrame. + + (* StructRecord + { + name := "CreateFrame"; + ty_params := []; + fields := + [ + ("created_address", Ty.path "alloy_primitives::bits::address::Address"); + ("frame_data", Ty.path "revm::frame::FrameData") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_frame_CreateFrame. + Definition Self : Ty.t := Ty.path "revm::frame::CreateFrame". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CreateFrame" |); + M.read (| Value.String "created_address" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::frame::CreateFrame", + "created_address" + |)); + M.read (| Value.String "frame_data" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::frame::CreateFrame", + "frame_data" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_frame_CreateFrame. + + (* StructRecord + { + name := "EOFCreateFrame"; + ty_params := []; + fields := + [ + ("created_address", Ty.path "alloy_primitives::bits::address::Address"); + ("return_memory_range", Ty.apply (Ty.path "core::ops::range::Range") [ Ty.path "usize" ]); + ("frame_data", Ty.path "revm::frame::FrameData") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_frame_EOFCreateFrame. + Definition Self : Ty.t := Ty.path "revm::frame::EOFCreateFrame". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "EOFCreateFrame" |); + M.read (| Value.String "created_address" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::frame::EOFCreateFrame", + "created_address" + |)); + M.read (| Value.String "return_memory_range" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::frame::EOFCreateFrame", + "return_memory_range" + |)); + M.read (| Value.String "frame_data" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::frame::EOFCreateFrame", + "frame_data" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_frame_EOFCreateFrame. + + (* StructRecord + { + name := "FrameData"; + ty_params := []; + fields := + [ + ("checkpoint", Ty.path "revm::journaled_state::JournalCheckpoint"); + ("interpreter", Ty.path "revm_interpreter::interpreter::Interpreter") + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_frame_FrameData. + Definition Self : Ty.t := Ty.path "revm::frame::FrameData". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "FrameData" |); + M.read (| Value.String "checkpoint" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::frame::FrameData", + "checkpoint" + |)); + M.read (| Value.String "interpreter" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::frame::FrameData", + "interpreter" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_frame_FrameData. + + (* + Enum Frame + { + ty_params := []; + variants := + [ + { + name := "Call"; + item := + StructTuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm::frame::CallFrame"; Ty.path "alloc::alloc::Global" ] + ]; + discriminant := None; + }; + { + name := "Create"; + item := + StructTuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm::frame::CreateFrame"; Ty.path "alloc::alloc::Global" ] + ]; + discriminant := None; + }; + { + name := "EOFCreate"; + item := + StructTuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm::frame::EOFCreateFrame"; Ty.path "alloc::alloc::Global" ] + ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_frame_Frame. + Definition Self : Ty.t := Ty.path "revm::frame::Frame". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| ฮณ, "revm::frame::Frame::Call", 0 |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Call" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::Create", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "Create" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::EOFCreate", + 0 + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_tuple_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "EOFCreate" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_frame_Frame. + + (* + Enum FrameResult + { + ty_params := []; + variants := + [ + { + name := "Call"; + item := + StructTuple + [ Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome" ]; + discriminant := None; + }; + { + name := "Create"; + item := + StructTuple + [ Ty.path "revm_interpreter::interpreter_action::create_outcome::CreateOutcome" ]; + discriminant := None; + }; + { + name := "EOFCreate"; + item := + StructTuple + [ Ty.path "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome" + ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_revm_frame_FrameResult. + Definition Self : Ty.t := Ty.path "revm::frame::FrameResult". + + (* + pub fn into_interpreter_result(self) -> InterpreterResult { + match self { + FrameResult::Call(outcome) => outcome.result, + FrameResult::Create(outcome) => outcome.result, + FrameResult::EOFCreate(outcome) => outcome.result, + } + } + *) + Definition into_interpreter_result (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Call", + 0 + |) in + let outcome := M.copy (| ฮณ0_0 |) in + M.SubPointer.get_struct_record_field (| + outcome, + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Create", + 0 + |) in + let outcome := M.copy (| ฮณ0_0 |) in + M.SubPointer.get_struct_record_field (| + outcome, + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::EOFCreate", + 0 + |) in + let outcome := M.copy (| ฮณ0_0 |) in + M.SubPointer.get_struct_record_field (| + outcome, + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_interpreter_result : + M.IsAssociatedFunction Self "into_interpreter_result" into_interpreter_result. + + (* + pub fn output(&self) -> Output { + match self { + FrameResult::Call(outcome) => Output::Call(outcome.result.output.clone()), + FrameResult::Create(outcome) => { + Output::Create(outcome.result.output.clone(), outcome.address) + } + FrameResult::EOFCreate(_) => { + panic!("EOFCreate can't be called from external world."); + } + } + } + *) + Definition output (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Call", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::Output::Call" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Create", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "revm_primitives::result::Output::Create" + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "output" + |) + ] + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "address" + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::EOFCreate", + 0 + |) in + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic_fmt", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_const", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "EOFCreate can't be called from external world." + |) + ] + |)) + ] + |) + ] + |) + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_output : M.IsAssociatedFunction Self "output" output. + + (* + pub fn gas(&self) -> &Gas { + match self { + FrameResult::Call(outcome) => &outcome.result.gas, + FrameResult::Create(outcome) => &outcome.result.gas, + FrameResult::EOFCreate(outcome) => &outcome.result.gas, + } + } + *) + Definition gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Call", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Create", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::EOFCreate", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_gas : M.IsAssociatedFunction Self "gas" gas. + + (* + pub fn gas_mut(&mut self) -> &mut Gas { + match self { + FrameResult::Call(outcome) => &mut outcome.result.gas, + FrameResult::Create(outcome) => &mut outcome.result.gas, + FrameResult::EOFCreate(outcome) => &mut outcome.result.gas, + } + } + *) + Definition gas_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Call", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Create", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::EOFCreate", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_gas_mut : M.IsAssociatedFunction Self "gas_mut" gas_mut. + + (* + pub fn interpreter_result(&self) -> &InterpreterResult { + match self { + FrameResult::Call(outcome) => &outcome.result, + FrameResult::Create(outcome) => &outcome.result, + FrameResult::EOFCreate(outcome) => &outcome.result, + } + } + *) + Definition interpreter_result (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Call", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Create", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::EOFCreate", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_interpreter_result : + M.IsAssociatedFunction Self "interpreter_result" interpreter_result. + + (* + pub fn interpreter_result_mut(&mut self) -> &InterpreterResult { + match self { + FrameResult::Call(outcome) => &mut outcome.result, + FrameResult::Create(outcome) => &mut outcome.result, + FrameResult::EOFCreate(outcome) => &mut outcome.result, + } + } + *) + Definition interpreter_result_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Call", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Create", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::EOFCreate", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| outcome |), + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "result" + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_interpreter_result_mut : + M.IsAssociatedFunction Self "interpreter_result_mut" interpreter_result_mut. + + (* + pub fn instruction_result(&self) -> InstructionResult { + self.interpreter_result().result + } + *) + Definition instruction_result (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameResult", + "interpreter_result", + [] + |), + [ M.read (| self |) ] + |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_instruction_result : + M.IsAssociatedFunction Self "instruction_result" instruction_result. + End Impl_revm_frame_FrameResult. + + (* + Enum FrameOrResult + { + ty_params := []; + variants := + [ + { + name := "Frame"; + item := StructTuple [ Ty.path "revm::frame::Frame" ]; + discriminant := None; + }; + { + name := "Result"; + item := StructTuple [ Ty.path "revm::frame::FrameResult" ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_revm_frame_Frame. + Definition Self : Ty.t := Ty.path "revm::frame::Frame". + + (* + pub fn new_create( + created_address: Address, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Frame::Create(Box::new(CreateFrame { + created_address, + frame_data: FrameData { + checkpoint, + interpreter, + }, + })) + } + *) + Definition new_create (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ created_address; checkpoint; interpreter ] => + ltac:(M.monadic + (let created_address := M.alloc (| created_address |) in + let checkpoint := M.alloc (| checkpoint |) in + let interpreter := M.alloc (| interpreter |) in + Value.StructTuple + "revm::frame::Frame::Create" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm::frame::CreateFrame"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [ + Value.StructRecord + "revm::frame::CreateFrame" + [ + ("created_address", M.read (| created_address |)); + ("frame_data", + Value.StructRecord + "revm::frame::FrameData" + [ + ("checkpoint", M.read (| checkpoint |)); + ("interpreter", M.read (| interpreter |)) + ]) + ] + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_create : M.IsAssociatedFunction Self "new_create" new_create. + + (* + pub fn new_call( + return_memory_range: Range, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Frame::Call(Box::new(CallFrame { + return_memory_range, + frame_data: FrameData { + checkpoint, + interpreter, + }, + })) + } + *) + Definition new_call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ return_memory_range; checkpoint; interpreter ] => + ltac:(M.monadic + (let return_memory_range := M.alloc (| return_memory_range |) in + let checkpoint := M.alloc (| checkpoint |) in + let interpreter := M.alloc (| interpreter |) in + Value.StructTuple + "revm::frame::Frame::Call" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm::frame::CallFrame"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [ + Value.StructRecord + "revm::frame::CallFrame" + [ + ("return_memory_range", M.read (| return_memory_range |)); + ("frame_data", + Value.StructRecord + "revm::frame::FrameData" + [ + ("checkpoint", M.read (| checkpoint |)); + ("interpreter", M.read (| interpreter |)) + ]) + ] + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_call : M.IsAssociatedFunction Self "new_call" new_call. + + (* + pub fn is_call(&self) -> bool { + matches!(self, Frame::Call { .. }) + } + *) + Definition is_call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := M.is_struct_tuple (| ฮณ, "revm::frame::Frame::Call" |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_call : M.IsAssociatedFunction Self "is_call" is_call. + + (* + pub fn is_create(&self) -> bool { + matches!(self, Frame::Create { .. }) + } + *) + Definition is_create (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let _ := M.is_struct_tuple (| ฮณ, "revm::frame::Frame::Create" |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_create : M.IsAssociatedFunction Self "is_create" is_create. + + (* + pub fn created_address(&self) -> Option
{ + match self { + Frame::Create(create_frame) => Some(create_frame.created_address), + _ => None, + } + } + *) + Definition created_address (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::Create", + 0 + |) in + let create_frame := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| create_frame |) |), + "revm::frame::CreateFrame", + "created_address" + |) + |) + ] + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_created_address : + M.IsAssociatedFunction Self "created_address" created_address. + + (* + pub fn into_frame_data(self) -> FrameData { + match self { + Frame::Call(call_frame) => call_frame.frame_data, + Frame::Create(create_frame) => create_frame.frame_data, + Frame::EOFCreate(eof_create_frame) => eof_create_frame.frame_data, + } + } + *) + Definition into_frame_data (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| ฮณ, "revm::frame::Frame::Call", 0 |) in + let call_frame := M.copy (| ฮณ0_0 |) in + M.SubPointer.get_struct_record_field (| + M.read (| call_frame |), + "revm::frame::CallFrame", + "frame_data" + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::Create", + 0 + |) in + let create_frame := M.copy (| ฮณ0_0 |) in + M.SubPointer.get_struct_record_field (| + M.read (| create_frame |), + "revm::frame::CreateFrame", + "frame_data" + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::EOFCreate", + 0 + |) in + let eof_create_frame := M.copy (| ฮณ0_0 |) in + M.SubPointer.get_struct_record_field (| + M.read (| eof_create_frame |), + "revm::frame::EOFCreateFrame", + "frame_data" + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_into_frame_data : + M.IsAssociatedFunction Self "into_frame_data" into_frame_data. + + (* + pub fn frame_data(&self) -> &FrameData { + match self { + Self::Call(call_frame) => &call_frame.frame_data, + Self::Create(create_frame) => &create_frame.frame_data, + Self::EOFCreate(eof_create_frame) => &eof_create_frame.frame_data, + } + } + *) + Definition frame_data (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| ฮณ, "revm::frame::Frame::Call", 0 |) in + let call_frame := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| call_frame |) |), + "revm::frame::CallFrame", + "frame_data" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::Create", + 0 + |) in + let create_frame := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| create_frame |) |), + "revm::frame::CreateFrame", + "frame_data" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::EOFCreate", + 0 + |) in + let eof_create_frame := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| eof_create_frame |) |), + "revm::frame::EOFCreateFrame", + "frame_data" + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_frame_data : M.IsAssociatedFunction Self "frame_data" frame_data. + + (* + pub fn frame_data_mut(&mut self) -> &mut FrameData { + match self { + Self::Call(call_frame) => &mut call_frame.frame_data, + Self::Create(create_frame) => &mut create_frame.frame_data, + Self::EOFCreate(eof_create_frame) => &mut eof_create_frame.frame_data, + } + } + *) + Definition frame_data_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| ฮณ, "revm::frame::Frame::Call", 0 |) in + let call_frame := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| call_frame |) |), + "revm::frame::CallFrame", + "frame_data" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::Create", + 0 + |) in + let create_frame := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| create_frame |) |), + "revm::frame::CreateFrame", + "frame_data" + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::Frame::EOFCreate", + 0 + |) in + let eof_create_frame := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| eof_create_frame |) |), + "revm::frame::EOFCreateFrame", + "frame_data" + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_frame_data_mut : + M.IsAssociatedFunction Self "frame_data_mut" frame_data_mut. + + (* + pub fn interpreter(&self) -> &Interpreter { + &self.frame_data().interpreter + } + *) + Definition interpreter (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| Ty.path "revm::frame::Frame", "frame_data", [] |), + [ M.read (| self |) ] + |), + "revm::frame::FrameData", + "interpreter" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_interpreter : M.IsAssociatedFunction Self "interpreter" interpreter. + + (* + pub fn interpreter_mut(&mut self) -> &mut Interpreter { + &mut self.frame_data_mut().interpreter + } + *) + Definition interpreter_mut (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| Ty.path "revm::frame::Frame", "frame_data_mut", [] |), + [ M.read (| self |) ] + |), + "revm::frame::FrameData", + "interpreter" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_interpreter_mut : + M.IsAssociatedFunction Self "interpreter_mut" interpreter_mut. + End Impl_revm_frame_Frame. + + Module Impl_revm_frame_FrameOrResult. + Definition Self : Ty.t := Ty.path "revm::frame::FrameOrResult". + + (* + pub fn new_create_frame( + created_address: Address, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Self::Frame(Frame::new_create(created_address, checkpoint, interpreter)) + } + *) + Definition new_create_frame (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ created_address; checkpoint; interpreter ] => + ltac:(M.monadic + (let created_address := M.alloc (| created_address |) in + let checkpoint := M.alloc (| checkpoint |) in + let interpreter := M.alloc (| interpreter |) in + Value.StructTuple + "revm::frame::FrameOrResult::Frame" + [ + M.call_closure (| + M.get_associated_function (| Ty.path "revm::frame::Frame", "new_create", [] |), + [ M.read (| created_address |); M.read (| checkpoint |); M.read (| interpreter |) ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_create_frame : + M.IsAssociatedFunction Self "new_create_frame" new_create_frame. + + (* + pub fn new_eofcreate_frame( + created_address: Address, + return_memory_range: Range, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Self::Frame(Frame::EOFCreate(Box::new(EOFCreateFrame { + created_address, + return_memory_range, + frame_data: FrameData { + checkpoint, + interpreter, + }, + }))) + } + *) + Definition new_eofcreate_frame (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ created_address; return_memory_range; checkpoint; interpreter ] => + ltac:(M.monadic + (let created_address := M.alloc (| created_address |) in + let return_memory_range := M.alloc (| return_memory_range |) in + let checkpoint := M.alloc (| checkpoint |) in + let interpreter := M.alloc (| interpreter |) in + Value.StructTuple + "revm::frame::FrameOrResult::Frame" + [ + Value.StructTuple + "revm::frame::Frame::EOFCreate" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm::frame::EOFCreateFrame"; Ty.path "alloc::alloc::Global" ], + "new", + [] + |), + [ + Value.StructRecord + "revm::frame::EOFCreateFrame" + [ + ("created_address", M.read (| created_address |)); + ("return_memory_range", M.read (| return_memory_range |)); + ("frame_data", + Value.StructRecord + "revm::frame::FrameData" + [ + ("checkpoint", M.read (| checkpoint |)); + ("interpreter", M.read (| interpreter |)) + ]) + ] + ] + |) + ] + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_eofcreate_frame : + M.IsAssociatedFunction Self "new_eofcreate_frame" new_eofcreate_frame. + + (* + pub fn new_call_frame( + return_memory_range: Range, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Self::Frame(Frame::new_call( + return_memory_range, + checkpoint, + interpreter, + )) + } + *) + Definition new_call_frame (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ return_memory_range; checkpoint; interpreter ] => + ltac:(M.monadic + (let return_memory_range := M.alloc (| return_memory_range |) in + let checkpoint := M.alloc (| checkpoint |) in + let interpreter := M.alloc (| interpreter |) in + Value.StructTuple + "revm::frame::FrameOrResult::Frame" + [ + M.call_closure (| + M.get_associated_function (| Ty.path "revm::frame::Frame", "new_call", [] |), + [ + M.read (| return_memory_range |); + M.read (| checkpoint |); + M.read (| interpreter |) + ] + |) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_call_frame : + M.IsAssociatedFunction Self "new_call_frame" new_call_frame. + + (* + pub fn new_create_result( + interpreter_result: InterpreterResult, + address: Option
, + ) -> Self { + FrameOrResult::Result(FrameResult::Create(CreateOutcome { + result: interpreter_result, + address, + })) + } + *) + Definition new_create_result (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ interpreter_result; address ] => + ltac:(M.monadic + (let interpreter_result := M.alloc (| interpreter_result |) in + let address := M.alloc (| address |) in + Value.StructTuple + "revm::frame::FrameOrResult::Result" + [ + Value.StructTuple + "revm::frame::FrameResult::Create" + [ + Value.StructRecord + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome" + [ ("result", M.read (| interpreter_result |)); ("address", M.read (| address |)) + ] + ] + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_create_result : + M.IsAssociatedFunction Self "new_create_result" new_create_result. + + (* + pub fn new_eofcreate_result( + interpreter_result: InterpreterResult, + address: Address, + return_memory_range: Range, + ) -> Self { + FrameOrResult::Result(FrameResult::EOFCreate(EOFCreateOutcome { + result: interpreter_result, + address, + return_memory_range, + })) + } + *) + Definition new_eofcreate_result (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ interpreter_result; address; return_memory_range ] => + ltac:(M.monadic + (let interpreter_result := M.alloc (| interpreter_result |) in + let address := M.alloc (| address |) in + let return_memory_range := M.alloc (| return_memory_range |) in + Value.StructTuple + "revm::frame::FrameOrResult::Result" + [ + Value.StructTuple + "revm::frame::FrameResult::EOFCreate" + [ + Value.StructRecord + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome" + [ + ("result", M.read (| interpreter_result |)); + ("address", M.read (| address |)); + ("return_memory_range", M.read (| return_memory_range |)) + ] + ] + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_eofcreate_result : + M.IsAssociatedFunction Self "new_eofcreate_result" new_eofcreate_result. + + (* + pub fn new_call_result( + interpreter_result: InterpreterResult, + memory_offset: Range, + ) -> Self { + FrameOrResult::Result(FrameResult::Call(CallOutcome { + result: interpreter_result, + memory_offset, + })) + } + *) + Definition new_call_result (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ interpreter_result; memory_offset ] => + ltac:(M.monadic + (let interpreter_result := M.alloc (| interpreter_result |) in + let memory_offset := M.alloc (| memory_offset |) in + Value.StructTuple + "revm::frame::FrameOrResult::Result" + [ + Value.StructTuple + "revm::frame::FrameResult::Call" + [ + Value.StructRecord + "revm_interpreter::interpreter_action::call_outcome::CallOutcome" + [ + ("result", M.read (| interpreter_result |)); + ("memory_offset", M.read (| memory_offset |)) + ] + ] + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new_call_result : + M.IsAssociatedFunction Self "new_call_result" new_call_result. + End Impl_revm_frame_FrameOrResult. +End frame. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler.md new file mode 100644 index 00000000..c1168cca --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler.md @@ -0,0 +1,1649 @@ +# ๐Ÿ“ handler.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + (* StructRecord + { + name := "Handler"; + ty_params := [ "H"; "EXT"; "DB" ]; + fields := + [ + ("cfg", Ty.path "revm_primitives::env::handler_cfg::HandlerCfg"); + ("instruction_table", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "revm_interpreter::opcode::InstructionTables") [ H ] ]); + ("registers", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply (Ty.path "revm::handler::register::HandleRegisters") [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ]); + ("validation", + Ty.apply + (Ty.path "revm::handler::handle_types::validation::ValidationHandler") + [ EXT; DB ]); + ("pre_execution", + Ty.apply + (Ty.path "revm::handler::handle_types::pre_execution::PreExecutionHandler") + [ EXT; DB ]); + ("post_execution", + Ty.apply + (Ty.path "revm::handler::handle_types::post_execution::PostExecutionHandler") + [ EXT; DB ]); + ("execution", + Ty.apply + (Ty.path "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ]) + ]; + } *) + + Module Impl_revm_handler_Handler_revm_evm_Evm_EXT_DB_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ]. + + (* + pub fn new(cfg: HandlerCfg) -> Self { + cfg_if::cfg_if! { + if #[cfg(feature = "optimism")] { + if cfg.is_optimism { + Handler::optimism_with_spec(cfg.spec_id) + } else { + Handler::mainnet_with_spec(cfg.spec_id) + } + } else { + Handler::mainnet_with_spec(cfg.spec_id) + } + } + } + *) + Definition new (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ cfg ] => + ltac:(M.monadic + (let cfg := M.alloc (| cfg |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet_with_spec", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + cfg, + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |) + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "new" (new EXT DB). + + (* + pub fn mainnet() -> Self { + Self { + cfg: HandlerCfg::new(SPEC::SPEC_ID), + instruction_table: Some(InstructionTables::new_plain::()), + registers: Vec::new(), + validation: ValidationHandler::new::(), + pre_execution: PreExecutionHandler::new::(), + post_execution: PostExecutionHandler::new::(), + execution: ExecutionHandler::new::(), + } + } + *) + Definition mainnet (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ SPEC ], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::handler::Handler" + [ + ("cfg", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + "new", + [] + |), + [ + M.read (| + M.get_constant (| "revm_primitives::specification::Spec::SPEC_ID" |) + |) + ] + |)); + ("instruction_table", + Value.StructTuple + "core::option::Option::Some" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm_interpreter::opcode::InstructionTables") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ], + "new_plain", + [ SPEC ] + |), + [] + |) + ]); + ("registers", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply (Ty.path "revm::handler::register::HandleRegisters") [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |)); + ("validation", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::handle_types::validation::ValidationHandler") + [ EXT; DB ], + "new", + [ SPEC ] + |), + [] + |)); + ("pre_execution", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::handle_types::pre_execution::PreExecutionHandler") + [ EXT; DB ], + "new", + [ SPEC ] + |), + [] + |)); + ("post_execution", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::handle_types::post_execution::PostExecutionHandler") + [ EXT; DB ], + "new", + [ SPEC ] + |), + [] + |)); + ("execution", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::handle_types::execution::ExecutionHandler") + [ EXT; DB ], + "new", + [ SPEC ] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_mainnet : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "mainnet" (mainnet EXT DB). + + (* + pub fn is_optimism(&self) -> bool { + self.cfg.is_optimism() + } + *) + Definition is_optimism (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::handler_cfg::HandlerCfg", + "is_optimism", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "cfg" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_is_optimism : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "is_optimism" (is_optimism EXT DB). + + (* + pub fn mainnet_with_spec(spec_id: SpecId) -> Self { + spec_to_generic!(spec_id, Self::mainnet::()) + } + *) + Definition mainnet_with_spec (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ spec_id ] => + ltac:(M.monadic + (let spec_id := M.alloc (| spec_id |) in + M.read (| + M.match_operator (| + spec_id, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::FRONTIER" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::FRONTIER_THAWING" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::FrontierSpec" ] + |), + [] + |) + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::HOMESTEAD" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::DAO_FORK" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::HomesteadSpec" ] + |), + [] + |) + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::TANGERINE" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::TangerineSpec" ] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::SpuriousDragonSpec" ] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::BYZANTIUM" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::ByzantiumSpec" ] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::PETERSBURG" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::CONSTANTINOPLE" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::PetersburgSpec" ] + |), + [] + |) + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::ISTANBUL" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::MUIR_GLACIER" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::IstanbulSpec" ] + |), + [] + |) + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::BERLIN" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::BerlinSpec" ] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::LONDON" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::ARROW_GLACIER" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::GRAY_GLACIER" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::LondonSpec" ] + |), + [] + |) + |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::MERGE" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::MergeSpec" ] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_primitives::specification::SpecId::SHANGHAI" + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::ShanghaiSpec" ] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::CANCUN" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::CancunSpec" ] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::LATEST" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::LatestSpec" ] + |), + [] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "revm_primitives::specification::SpecId::PRAGUE" |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ Ty.path "revm_primitives::specification::PragueSpec" ] + |), + [] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_mainnet_with_spec : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "mainnet_with_spec" (mainnet_with_spec EXT DB). + + (* + pub fn cfg(&self) -> HandlerCfg { + self.cfg + } + *) + Definition cfg (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "cfg" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_cfg : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "cfg" (cfg EXT DB). + + (* + pub fn take_instruction_table(&mut self) -> Option>> { + self.instruction_table.take() + } + *) + Definition take_instruction_table (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "revm_interpreter::opcode::InstructionTables") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + ], + "take", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "instruction_table" + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_take_instruction_table : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "take_instruction_table" (take_instruction_table EXT DB). + + (* + pub fn set_instruction_table(&mut self, table: InstructionTables<'a, Evm<'a, EXT, DB>>) { + self.instruction_table = Some(table); + } + *) + Definition set_instruction_table (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; table ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let table := M.alloc (| table |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "instruction_table" + |), + Value.StructTuple "core::option::Option::Some" [ M.read (| table |) ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_instruction_table : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "set_instruction_table" (set_instruction_table EXT DB). + + (* + pub fn pre_execution(&self) -> &PreExecutionHandler<'a, EXT, DB> { + &self.pre_execution + } + *) + Definition pre_execution (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "pre_execution" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pre_execution : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "pre_execution" (pre_execution EXT DB). + + (* + pub fn post_execution(&self) -> &PostExecutionHandler<'a, EXT, DB> { + &self.post_execution + } + *) + Definition post_execution (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "post_execution" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_post_execution : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "post_execution" (post_execution EXT DB). + + (* + pub fn execution(&self) -> &ExecutionHandler<'a, EXT, DB> { + &self.execution + } + *) + Definition execution (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "execution" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_execution : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "execution" (execution EXT DB). + + (* + pub fn validation(&self) -> &ValidationHandler<'a, EXT, DB> { + &self.validation + } + *) + Definition validation (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "validation" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_validation : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "validation" (validation EXT DB). + + (* + pub fn append_handler_register(&mut self, register: HandleRegisters) { + register.register(self); + self.registers.push(register); + } + *) + Definition append_handler_register (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; register ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let register := M.alloc (| register |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::handler::register::HandleRegisters") [ EXT; DB ], + "register", + [] + |), + [ register; M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply (Ty.path "revm::handler::register::HandleRegisters") [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "registers" + |); + M.read (| register |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_append_handler_register : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "append_handler_register" + (append_handler_register EXT DB). + + (* + pub fn append_handler_register_plain(&mut self, register: HandleRegister) { + register(self); + self.registers.push(HandleRegisters::Plain(register)); + } + *) + Definition append_handler_register_plain + (EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; register ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let register := M.alloc (| register |) in + M.read (| + let~ _ := + M.alloc (| M.call_closure (| M.read (| register |), [ M.read (| self |) ] |) |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply (Ty.path "revm::handler::register::HandleRegisters") [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "registers" + |); + Value.StructTuple + "revm::handler::register::HandleRegisters::Plain" + [ M.read (| register |) ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_append_handler_register_plain : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "append_handler_register_plain" + (append_handler_register_plain EXT DB). + + (* + pub fn append_handler_register_box(&mut self, register: HandleRegisterBox) { + register(self); + self.registers.push(HandleRegisters::Box(register)); + } + *) + Definition append_handler_register_box (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; register ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let register := M.alloc (| register |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ] + ] + ] + ], + "call", + [] + |), + [ register; Value.Tuple [ M.read (| self |) ] ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply (Ty.path "revm::handler::register::HandleRegisters") [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "registers" + |); + Value.StructTuple + "revm::handler::register::HandleRegisters::Box" + [ (* Unsize *) M.pointer_coercion (M.read (| register |)) ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_append_handler_register_box : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "append_handler_register_box" + (append_handler_register_box EXT DB). + + (* + pub fn pop_handle_register(&mut self) -> Option> { + let out = self.registers.pop(); + if out.is_some() { + let registers = core::mem::take(&mut self.registers); + let mut base_handler = Handler::mainnet_with_spec(self.cfg.spec_id); + // apply all registers to default handeler and raw mainnet instruction table. + for register in registers { + base_handler.append_handler_register(register) + } + *self = base_handler; + } + out + } + *) + Definition pop_handle_register (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ out := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply (Ty.path "revm::handler::register::HandleRegisters") [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + "pop", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "registers" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "revm::handler::register::HandleRegisters") + [ EXT; DB ] + ], + "is_some", + [] + |), + [ out ] + |) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ registers := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::take", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "revm::handler::register::HandleRegisters") + [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "registers" + |) + ] + |) + |) in + let~ base_handler := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet_with_spec", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "cfg" + |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |) + |) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "revm::handler::register::HandleRegisters") + [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| registers |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.apply + (Ty.path + "revm::handler::register::HandleRegisters") + [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let register := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ + Ty.apply + (Ty.path "revm::evm::Evm") + [ EXT; DB ]; + EXT; + DB + ], + "append_handler_register", + [] + |), + [ base_handler; M.read (| register |) ] + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := M.write (| M.read (| self |), M.read (| base_handler |) |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + out + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_pop_handle_register : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "pop_handle_register" (pop_handle_register EXT DB). + + (* + pub fn create_handle_generic(&mut self) -> EvmHandler<'a, EXT, DB> { + let registers = core::mem::take(&mut self.registers); + let mut base_handler = Handler::mainnet::(); + // apply all registers to default handeler and raw mainnet instruction table. + for register in registers { + base_handler.append_handler_register(register) + } + base_handler + } + *) + Definition create_handle_generic (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ SPEC ], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ registers := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::take", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply (Ty.path "revm::handler::register::HandleRegisters") [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "registers" + |) + ] + |) + |) in + let~ base_handler := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet", + [ SPEC ] + |), + [] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "revm::handler::register::HandleRegisters") + [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| registers |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.apply + (Ty.path "revm::handler::register::HandleRegisters") + [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let register := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; + EXT; + DB + ], + "append_handler_register", + [] + |), + [ base_handler; M.read (| register |) ] + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + base_handler + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_create_handle_generic : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "create_handle_generic" (create_handle_generic EXT DB). + + (* + pub fn modify_spec_id(&mut self, spec_id: SpecId) { + if self.cfg.spec_id == spec_id { + return; + } + + let registers = core::mem::take(&mut self.registers); + // register for optimism is added as a register, so we need to create mainnet handler here. + let mut handler = Handler::mainnet_with_spec(spec_id); + // apply all registers to default handler and raw mainnet instruction table. + for register in registers { + handler.append_handler_register(register) + } + handler.cfg = self.cfg(); + handler.cfg.spec_id = spec_id; + *self = handler; + } + *) + Definition modify_spec_id (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; spec_id ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let spec_id := M.alloc (| spec_id |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::specification::SpecId", + [ Ty.path "revm_primitives::specification::SpecId" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "cfg" + |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |); + spec_id + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| M.read (| M.return_ (| Value.Tuple [] |) |) |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ registers := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::take", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "revm::handler::register::HandleRegisters") + [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::Handler", + "registers" + |) + ] + |) + |) in + let~ handler := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "mainnet_with_spec", + [] + |), + [ M.read (| spec_id |) ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "revm::handler::register::HandleRegisters") + [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| registers |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.apply + (Ty.path "revm::handler::register::HandleRegisters") + [ EXT; DB ]; + Ty.path "alloc::alloc::Global" + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let register := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ + Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; + EXT; + DB + ], + "append_handler_register", + [] + |), + [ handler; M.read (| register |) ] + |) + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + handler, + "revm::handler::Handler", + "cfg" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "cfg", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + handler, + "revm::handler::Handler", + "cfg" + |), + "revm_primitives::env::handler_cfg::HandlerCfg", + "spec_id" + |), + M.read (| spec_id |) + |) in + let~ _ := M.write (| M.read (| self |), M.read (| handler |) |) in + M.alloc (| Value.Tuple [] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_modify_spec_id : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "modify_spec_id" (modify_spec_id EXT DB). + End Impl_revm_handler_Handler_revm_evm_Evm_EXT_DB_EXT_DB. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/execution.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/execution.md new file mode 100644 index 00000000..3d095b2e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/execution.md @@ -0,0 +1,1545 @@ +# ๐Ÿ“ execution.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler/handle_types/execution.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + Module handle_types. + Module execution. + Axiom LastFrameReturnHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::execution::LastFrameReturnHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom FrameCallHandle : + forall (EXT DB : Ty.t), + (Ty.apply (Ty.path "revm::handler::handle_types::execution::FrameCallHandle") [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom FrameCallReturnHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::execution::FrameCallReturnHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom InsertCallOutcomeHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::execution::InsertCallOutcomeHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom FrameCreateHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::execution::FrameCreateHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom FrameCreateReturnHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::execution::FrameCreateReturnHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom InsertCreateOutcomeHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::execution::InsertCreateOutcomeHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom FrameEOFCreateHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::execution::FrameEOFCreateHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom FrameEOFCreateReturnHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::execution::FrameEOFCreateReturnHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom InsertEOFCreateOutcomeHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::execution::InsertEOFCreateOutcomeHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + (* StructRecord + { + name := "ExecutionHandler"; + ty_params := [ "EXT"; "DB" ]; + fields := + [ + ("last_frame_return", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("call", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("call_return", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("insert_call_outcome", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("create", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("create_return", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("insert_create_outcome", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("eofcreate", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("eofcreate_return", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("insert_eofcreate_outcome", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_revm_handler_handle_types_execution_ExecutionHandler_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::handler::handle_types::execution::ExecutionHandler") [ EXT; DB ]. + + (* + pub fn new() -> Self { + Self { + last_frame_return: Arc::new(mainnet::last_frame_return::), + call: Arc::new(mainnet::call::), + call_return: Arc::new(mainnet::call_return::), + insert_call_outcome: Arc::new(mainnet::insert_call_outcome), + create: Arc::new(mainnet::create::), + create_return: Arc::new(mainnet::create_return::), + insert_create_outcome: Arc::new(mainnet::insert_create_outcome), + eofcreate: Arc::new(mainnet::eofcreate::), + eofcreate_return: Arc::new(mainnet::eofcreate_return::), + insert_eofcreate_outcome: Arc::new(mainnet::insert_eofcreate_outcome), + } + } + *) + Definition new (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ SPEC ], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::handler::handle_types::execution::ExecutionHandler" + [ + ("last_frame_return", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::FrameResult" ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::last_frame_return", + [ SPEC; EXT; DB ] + |) + ] + |))); + ("call", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::call", + [ SPEC; EXT; DB ] + |) + ] + |))); + ("call_return", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm::frame::CallFrame"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "revm_interpreter::interpreter::InterpreterResult" + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::call_return", + [ EXT; DB ] + |) + ] + |))); + ("insert_call_outcome", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::Frame" ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory" + ]; + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome" + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::insert_call_outcome", + [ EXT; DB ] + |) + ] + |))); + ("create", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::create", + [ SPEC; EXT; DB ] + |) + ] + |))); + ("create_return", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm::frame::CreateFrame"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "revm_interpreter::interpreter::InterpreterResult" + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::create_return", + [ SPEC; EXT; DB ] + |) + ] + |))); + ("insert_create_outcome", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::Frame" ]; + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome" + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::insert_create_outcome", + [ EXT; DB ] + |) + ] + |))); + ("eofcreate", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::eofcreate", + [ SPEC; EXT; DB ] + |) + ] + |))); + ("eofcreate_return", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm::frame::EOFCreateFrame"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "revm_interpreter::interpreter::InterpreterResult" + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::eofcreate_return", + [ SPEC; EXT; DB ] + |) + ] + |))); + ("insert_eofcreate_outcome", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::Frame" ]; + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome" + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::execution::insert_eofcreate_outcome", + [ EXT; DB ] + |) + ] + |))) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "new" (new EXT DB). + (* + pub fn last_frame_return( + &self, + context: &mut Context, + frame_result: &mut FrameResult, + ) -> Result<(), EVMError> { + (self.last_frame_return)(context, frame_result) + } + *) + Definition last_frame_return (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; frame_result ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let frame_result := M.alloc (| frame_result |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::FrameResult" ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "last_frame_return" + |) + ] + |); + Value.Tuple [ M.read (| context |); M.read (| frame_result |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_last_frame_return : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "last_frame_return" (last_frame_return EXT DB). + + (* + pub fn call( + &self, + context: &mut Context, + inputs: Box, + ) -> Result> { + (self.call)(context, inputs.clone()) + } + *) + Definition call (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "call" + |) + ] + |); + Value.Tuple + [ + M.read (| context |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ inputs ] + |) + ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_call : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "call" (call EXT DB). + + (* + pub fn call_return( + &self, + context: &mut Context, + frame: Box, + interpreter_result: InterpreterResult, + ) -> Result> { + (self.call_return)(context, frame, interpreter_result) + } + *) + Definition call_return (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; frame; interpreter_result ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let interpreter_result := M.alloc (| interpreter_result |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm::frame::CallFrame"; Ty.path "alloc::alloc::Global" ]; + Ty.path "revm_interpreter::interpreter::InterpreterResult" + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "call_return" + |) + ] + |); + Value.Tuple + [ M.read (| context |); M.read (| frame |); M.read (| interpreter_result |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_call_return : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "call_return" (call_return EXT DB). + + (* + pub fn insert_call_outcome( + &self, + context: &mut Context, + frame: &mut Frame, + shared_memory: &mut SharedMemory, + outcome: CallOutcome, + ) -> Result<(), EVMError> { + (self.insert_call_outcome)(context, frame, shared_memory, outcome) + } + *) + Definition insert_call_outcome (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; frame; shared_memory; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let shared_memory := M.alloc (| shared_memory |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::Frame" ]; + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory" ]; + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome" + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "insert_call_outcome" + |) + ] + |); + Value.Tuple + [ + M.read (| context |); + M.read (| frame |); + M.read (| shared_memory |); + M.read (| outcome |) + ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_call_outcome : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "insert_call_outcome" (insert_call_outcome EXT DB). + + (* + pub fn create( + &self, + context: &mut Context, + inputs: Box, + ) -> Result> { + (self.create)(context, inputs) + } + *) + Definition create (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "create" + |) + ] + |); + Value.Tuple [ M.read (| context |); M.read (| inputs |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_create : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "create" (create EXT DB). + + (* + pub fn create_return( + &self, + context: &mut Context, + frame: Box, + interpreter_result: InterpreterResult, + ) -> Result> { + (self.create_return)(context, frame, interpreter_result) + } + *) + Definition create_return (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; frame; interpreter_result ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let interpreter_result := M.alloc (| interpreter_result |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm::frame::CreateFrame"; Ty.path "alloc::alloc::Global" ]; + Ty.path "revm_interpreter::interpreter::InterpreterResult" + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "create_return" + |) + ] + |); + Value.Tuple + [ M.read (| context |); M.read (| frame |); M.read (| interpreter_result |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_create_return : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "create_return" (create_return EXT DB). + + (* + pub fn insert_create_outcome( + &self, + context: &mut Context, + frame: &mut Frame, + outcome: CreateOutcome, + ) -> Result<(), EVMError> { + (self.insert_create_outcome)(context, frame, outcome) + } + *) + Definition insert_create_outcome (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; frame; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::Frame" ]; + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome" + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "insert_create_outcome" + |) + ] + |); + Value.Tuple [ M.read (| context |); M.read (| frame |); M.read (| outcome |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_create_outcome : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "insert_create_outcome" + (insert_create_outcome EXT DB). + + (* + pub fn eofcreate( + &self, + context: &mut Context, + inputs: Box, + ) -> Result> { + (self.eofcreate)(context, inputs) + } + *) + Definition eofcreate (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "eofcreate" + |) + ] + |); + Value.Tuple [ M.read (| context |); M.read (| inputs |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_eofcreate : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "eofcreate" (eofcreate EXT DB). + + (* + pub fn eofcreate_return( + &self, + context: &mut Context, + frame: Box, + interpreter_result: InterpreterResult, + ) -> Result> { + (self.eofcreate_return)(context, frame, interpreter_result) + } + *) + Definition eofcreate_return (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; frame; interpreter_result ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let interpreter_result := M.alloc (| interpreter_result |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ Ty.path "revm::frame::EOFCreateFrame"; Ty.path "alloc::alloc::Global" ]; + Ty.path "revm_interpreter::interpreter::InterpreterResult" + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "eofcreate_return" + |) + ] + |); + Value.Tuple + [ M.read (| context |); M.read (| frame |); M.read (| interpreter_result |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_eofcreate_return : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "eofcreate_return" (eofcreate_return EXT DB). + + (* + pub fn insert_eofcreate_outcome( + &self, + context: &mut Context, + frame: &mut Frame, + outcome: EOFCreateOutcome, + ) -> Result<(), EVMError> { + (self.insert_eofcreate_outcome)(context, frame, outcome) + } + *) + Definition insert_eofcreate_outcome + (EXT DB : Ty.t) + (ฯ„ : list Ty.t) + (ฮฑ : list Value.t) + : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; frame; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::Frame" ]; + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome" + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::execution::ExecutionHandler", + "insert_eofcreate_outcome" + |) + ] + |); + Value.Tuple [ M.read (| context |); M.read (| frame |); M.read (| outcome |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_insert_eofcreate_outcome : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction + (Self EXT DB) + "insert_eofcreate_outcome" + (insert_eofcreate_outcome EXT DB). + End Impl_revm_handler_handle_types_execution_ExecutionHandler_EXT_DB. + + End execution. + End handle_types. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/post_execution.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/post_execution.md new file mode 100644 index 00000000..67533770 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/post_execution.md @@ -0,0 +1,728 @@ +# ๐Ÿ“ post_execution.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler/handle_types/post_execution.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + Module handle_types. + Module post_execution. + Axiom ReimburseCallerHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::post_execution::ReimburseCallerHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom RewardBeneficiaryHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::post_execution::RewardBeneficiaryHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom OutputHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::post_execution::OutputHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom EndHandle : + forall (EXT DB : Ty.t), + (Ty.apply (Ty.path "revm::handler::handle_types::post_execution::EndHandle") [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom ClearHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::post_execution::ClearHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + (* StructRecord + { + name := "PostExecutionHandler"; + ty_params := [ "EXT"; "DB" ]; + fields := + [ + ("reimburse_caller", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("reward_beneficiary", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("output", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("end_", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("clear", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_revm_handler_handle_types_post_execution_PostExecutionHandler_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply + (Ty.path "revm::handler::handle_types::post_execution::PostExecutionHandler") + [ EXT; DB ]. + + (* + pub fn new() -> Self { + Self { + reimburse_caller: Arc::new(mainnet::reimburse_caller::), + reward_beneficiary: Arc::new(mainnet::reward_beneficiary::), + output: Arc::new(mainnet::output::), + end: Arc::new(mainnet::end::), + clear: Arc::new(mainnet::clear::), + } + } + *) + Definition new (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ SPEC ], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::handler::handle_types::post_execution::PostExecutionHandler" + [ + ("reimburse_caller", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&") [ Ty.path "revm_interpreter::gas::Gas" ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::post_execution::reimburse_caller", + [ SPEC; EXT; DB ] + |) + ] + |))); + ("reward_beneficiary", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&") [ Ty.path "revm_interpreter::gas::Gas" ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::post_execution::reward_beneficiary", + [ SPEC; EXT; DB ] + |) + ] + |))); + ("output", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.path "revm::frame::FrameResult" + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::post_execution::output", + [ EXT; DB ] + |) + ] + |))); + ("end_", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::post_execution::end", + [ EXT; DB ] + |) + ] + |))); + ("clear", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ] + ] + (Ty.tuple []); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::post_execution::clear", + [ EXT; DB ] + |) + ] + |))) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "new" (new EXT DB). + (* + pub fn reimburse_caller( + &self, + context: &mut Context, + gas: &Gas, + ) -> Result<(), EVMError> { + (self.reimburse_caller)(context, gas) + } + *) + Definition reimburse_caller (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; gas ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let gas := M.alloc (| gas |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&") [ Ty.path "revm_interpreter::gas::Gas" ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::post_execution::PostExecutionHandler", + "reimburse_caller" + |) + ] + |); + Value.Tuple [ M.read (| context |); M.read (| gas |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_reimburse_caller : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "reimburse_caller" (reimburse_caller EXT DB). + + (* + pub fn reward_beneficiary( + &self, + context: &mut Context, + gas: &Gas, + ) -> Result<(), EVMError> { + (self.reward_beneficiary)(context, gas) + } + *) + Definition reward_beneficiary (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; gas ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let gas := M.alloc (| gas |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&") [ Ty.path "revm_interpreter::gas::Gas" ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::post_execution::PostExecutionHandler", + "reward_beneficiary" + |) + ] + |); + Value.Tuple [ M.read (| context |); M.read (| gas |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_reward_beneficiary : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "reward_beneficiary" (reward_beneficiary EXT DB). + + (* + pub fn output( + &self, + context: &mut Context, + result: FrameResult, + ) -> Result> { + (self.output)(context, result) + } + *) + Definition output (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; result ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let result := M.alloc (| result |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.path "revm::frame::FrameResult" + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::post_execution::PostExecutionHandler", + "output" + |) + ] + |); + Value.Tuple [ M.read (| context |); M.read (| result |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_output : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "output" (output EXT DB). + + (* + pub fn end( + &self, + context: &mut Context, + end_output: Result>, + ) -> Result> { + (self.end)(context, end_output) + } + *) + Definition end_ (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context; end_output ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let end_output := M.alloc (| end_output |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply (Ty.path "revm_primitives::result::EVMError") [ Ty.associated ] + ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::post_execution::PostExecutionHandler", + "end" + |) + ] + |); + Value.Tuple [ M.read (| context |); M.read (| end_output |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_end_ : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "end_" (end_ EXT DB). + + (* + pub fn clear(&self, context: &mut Context) { + (self.clear)(context) + } + *) + Definition clear (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::post_execution::PostExecutionHandler", + "clear" + |) + ] + |); + Value.Tuple [ M.read (| context |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_clear : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "clear" (clear EXT DB). + End Impl_revm_handler_handle_types_post_execution_PostExecutionHandler_EXT_DB. + + End post_execution. + End handle_types. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/pre_execution.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/pre_execution.md new file mode 100644 index 00000000..1d3d7cdf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/pre_execution.md @@ -0,0 +1,403 @@ +# ๐Ÿ“ pre_execution.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler/handle_types/pre_execution.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + Module handle_types. + Module pre_execution. + Axiom LoadPrecompilesHandle : + forall (DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::pre_execution::LoadPrecompilesHandle") + [ DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ Ty.dyn [ ("core::ops::function::Fn::Trait", []) ]; Ty.path "alloc::alloc::Global" ]). + + Axiom LoadAccountsHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::pre_execution::LoadAccountsHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom DeductCallerHandle : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::pre_execution::DeductCallerHandle") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + (* StructRecord + { + name := "PreExecutionHandler"; + ty_params := [ "EXT"; "DB" ]; + fields := + [ + ("load_precompiles", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn [ ("core::ops::function::Fn::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ]); + ("load_accounts", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("deduct_caller", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_revm_handler_handle_types_pre_execution_PreExecutionHandler_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply + (Ty.path "revm::handler::handle_types::pre_execution::PreExecutionHandler") + [ EXT; DB ]. + + (* + pub fn new() -> Self { + Self { + load_precompiles: Arc::new(mainnet::load_precompiles::), + load_accounts: Arc::new(mainnet::load_accounts::), + deduct_caller: Arc::new(mainnet::deduct_caller::), + } + } + *) + Definition new (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ SPEC ], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::handler::handle_types::pre_execution::PreExecutionHandler" + [ + ("load_precompiles", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [] + (Ty.apply + (Ty.path "revm::context::context_precompiles::ContextPrecompiles") + [ DB ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::pre_execution::load_precompiles", + [ SPEC; DB ] + |) + ] + |))); + ("load_accounts", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::pre_execution::load_accounts", + [ SPEC; EXT; DB ] + |) + ] + |))); + ("deduct_caller", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::pre_execution::deduct_caller", + [ SPEC; EXT; DB ] + |) + ] + |))) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "new" (new EXT DB). + (* + pub fn deduct_caller(&self, context: &mut Context) -> Result<(), EVMError> { + (self.deduct_caller)(context) + } + *) + Definition deduct_caller (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::pre_execution::PreExecutionHandler", + "deduct_caller" + |) + ] + |); + Value.Tuple [ M.read (| context |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_deduct_caller : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "deduct_caller" (deduct_caller EXT DB). + + (* + pub fn load_accounts(&self, context: &mut Context) -> Result<(), EVMError> { + (self.load_accounts)(context) + } + *) + Definition load_accounts (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::pre_execution::PreExecutionHandler", + "load_accounts" + |) + ] + |); + Value.Tuple [ M.read (| context |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_accounts : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "load_accounts" (load_accounts EXT DB). + + (* + pub fn load_precompiles(&self) -> ContextPrecompiles { + (self.load_precompiles)() + } + *) + Definition load_precompiles (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn [ ("core::ops::function::Fn::Trait", []) ], + [ Ty.tuple [] ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn [ ("core::ops::function::Fn::Trait", []) ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::pre_execution::PreExecutionHandler", + "load_precompiles" + |) + ] + |); + Value.Tuple [] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_precompiles : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "load_precompiles" (load_precompiles EXT DB). + End Impl_revm_handler_handle_types_pre_execution_PreExecutionHandler_EXT_DB. + + End pre_execution. + End handle_types. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/validation.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/validation.md new file mode 100644 index 00000000..c3335678 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/handle_types/validation.md @@ -0,0 +1,418 @@ +# ๐Ÿ“ validation.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler/handle_types/validation.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + Module handle_types. + Module validation. + Axiom ValidateEnvHandle : + forall (DB : Ty.t), + (Ty.apply (Ty.path "revm::handler::handle_types::validation::ValidateEnvHandle") [ DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom ValidateTxEnvAgainstState : + forall (EXT DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::validation::ValidateTxEnvAgainstState") + [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + Axiom ValidateInitialTxGasHandle : + forall (DB : Ty.t), + (Ty.apply + (Ty.path "revm::handler::handle_types::validation::ValidateInitialTxGasHandle") + [ DB ]) = + (Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + (* StructRecord + { + name := "ValidationHandler"; + ty_params := [ "EXT"; "DB" ]; + fields := + [ + ("initial_tx_gas", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("tx_against_state", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]); + ("env", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ]; + } *) + + Module Impl_revm_handler_handle_types_validation_ValidationHandler_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply + (Ty.path "revm::handler::handle_types::validation::ValidationHandler") + [ EXT; DB ]. + + (* + pub fn new() -> Self { + Self { + initial_tx_gas: Arc::new(mainnet::validate_initial_tx_gas::), + env: Arc::new(mainnet::validate_env::), + tx_against_state: Arc::new(mainnet::validate_tx_against_state::), + } + } + *) + Definition new (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [ SPEC ], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::handler::handle_types::validation::ValidationHandler" + [ + ("initial_tx_gas", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::Env" ] ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "u64"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::validation::validate_initial_tx_gas", + [ SPEC; DB ] + |) + ] + |))); + ("env", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::Env" ] ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::validation::validate_env", + [ SPEC; DB ] + |) + ] + |))); + ("tx_against_state", + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.get_function (| + "revm::handler::mainnet::validation::validate_tx_against_state", + [ SPEC; EXT; DB ] + |) + ] + |))) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "new" (new EXT DB). + (* + pub fn env(&self, env: &Env) -> Result<(), EVMError> { + (self.env)(env) + } + *) + Definition env (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; env ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let env := M.alloc (| env |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ Ty.tuple [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::Env" ] ] ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::validation::ValidationHandler", + "env" + |) + ] + |); + Value.Tuple [ M.read (| env |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_env : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "env" (env EXT DB). + + (* + pub fn initial_tx_gas(&self, env: &Env) -> Result> { + (self.initial_tx_gas)(env) + } + *) + Definition initial_tx_gas (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; env ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let env := M.alloc (| env |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ Ty.tuple [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::env::Env" ] ] ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::validation::ValidationHandler", + "initial_tx_gas" + |) + ] + |); + Value.Tuple [ M.read (| env |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_initial_tx_gas : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "initial_tx_gas" (initial_tx_gas EXT DB). + + (* + pub fn tx_against_state( + &self, + context: &mut Context, + ) -> Result<(), EVMError> { + (self.tx_against_state)(context) + } + *) + Definition tx_against_state (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::handler::handle_types::validation::ValidationHandler", + "tx_against_state" + |) + ] + |); + Value.Tuple [ M.read (| context |) ] + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_tx_against_state : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "tx_against_state" (tx_against_state EXT DB). + End Impl_revm_handler_handle_types_validation_ValidationHandler_EXT_DB. + + End validation. + End handle_types. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/execution.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/execution.md new file mode 100644 index 00000000..aa7da88f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/execution.md @@ -0,0 +1,1323 @@ +# ๐Ÿ“ execution.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler/mainnet/execution.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + Module mainnet. + Module execution. + (* + pub fn frame_return_with_refund_flag( + env: &Env, + frame_result: &mut FrameResult, + refund_enabled: bool, + ) { + let instruction_result = frame_result.interpreter_result().result; + let gas = frame_result.gas_mut(); + let remaining = gas.remaining(); + let refunded = gas.refunded(); + + // Spend the gas limit. Gas is reimbursed when the tx returns successfully. + *gas = Gas::new_spent(env.tx.gas_limit); + + match instruction_result { + return_ok!() => { + gas.erase_cost(remaining); + gas.record_refund(refunded); + } + return_revert!() => { + gas.erase_cost(remaining); + } + _ => {} + } + + // Calculate gas refund for transaction. + // If config is set to disable gas refund, it will return 0. + // If spec is set to london, it will decrease the maximum refund amount to 5th part of + // gas spend. (Before london it was 2th part of gas spend) + if refund_enabled { + // EIP-3529: Reduction in refunds + gas.set_final_refund(SPEC::SPEC_ID.is_enabled_in(SpecId::LONDON)); + } + } + *) + Definition frame_return_with_refund_flag (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC ], [ env; frame_result; refund_enabled ] => + ltac:(M.monadic + (let env := M.alloc (| env |) in + let frame_result := M.alloc (| frame_result |) in + let refund_enabled := M.alloc (| refund_enabled |) in + M.read (| + let~ instruction_result := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameResult", + "interpreter_result", + [] + |), + [ M.read (| frame_result |) ] + |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + |) in + let~ gas := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameResult", + "gas_mut", + [] + |), + [ M.read (| frame_result |) ] + |) + |) in + let~ remaining := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ M.read (| gas |) ] + |) + |) in + let~ refunded := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ M.read (| gas |) ] + |) + |) in + let~ _ := + M.write (| + M.read (| gas |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "new_spent", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_limit" + |) + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + instruction_result, + [ + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Continue" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Stop" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Return" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::SelfDestruct" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::ReturnContract" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "erase_cost", + [] + |), + [ M.read (| gas |); M.read (| remaining |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "record_refund", + [] + |), + [ M.read (| gas |); M.read (| refunded |) ] + |) + |) in + M.alloc (| Value.Tuple [] |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => + ltac:(M.monadic + (M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::Revert" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::CallTooDeep" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::InstructionResult::OutOfFunds" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "erase_cost", + [] + |), + [ M.read (| gas |); M.read (| remaining |) ] + |) + |) in + M.alloc (| Value.Tuple [] |) + | _ => M.impossible (||) + end)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use refund_enabled in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "set_final_refund", + [] + |), + [ + M.read (| gas |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| + M.get_constant (| + "revm_primitives::specification::Spec::SPEC_ID" + |) + |); + Value.StructTuple + "revm_primitives::specification::SpecId::LONDON" + [] + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_frame_return_with_refund_flag : + M.IsFunction + "revm::handler::mainnet::execution::frame_return_with_refund_flag" + frame_return_with_refund_flag. + + (* + pub fn last_frame_return( + context: &mut Context, + frame_result: &mut FrameResult, + ) -> Result<(), EVMError> { + frame_return_with_refund_flag::(&context.evm.env, frame_result, true); + Ok(()) + } + *) + Definition last_frame_return (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context; frame_result ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let frame_result := M.alloc (| frame_result |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm::handler::mainnet::execution::frame_return_with_refund_flag", + [ SPEC ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |); + M.read (| frame_result |); + Value.Bool true + ] + |) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_last_frame_return : + M.IsFunction "revm::handler::mainnet::execution::last_frame_return" last_frame_return. + + (* + pub fn call( + context: &mut Context, + inputs: Box, + ) -> Result> { + context.evm.make_call_frame(&inputs) + } + *) + Definition call (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context; inputs ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + "make_call_frame", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |); + M.read (| inputs |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_call : M.IsFunction "revm::handler::mainnet::execution::call" call. + + (* + pub fn call_return( + context: &mut Context, + frame: Box, + interpreter_result: InterpreterResult, + ) -> Result> { + context + .evm + .call_return(&interpreter_result, frame.frame_data.checkpoint); + Ok(CallOutcome::new( + interpreter_result, + frame.return_memory_range, + )) + } + *) + Definition call_return (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ EXT; DB ], [ context; frame; interpreter_result ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let interpreter_result := M.alloc (| interpreter_result |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "call_return", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |); + interpreter_result; + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| frame |), + "revm::frame::CallFrame", + "frame_data" + |), + "revm::frame::FrameData", + "checkpoint" + |) + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "new", + [] + |), + [ + M.read (| interpreter_result |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| frame |), + "revm::frame::CallFrame", + "return_memory_range" + |) + |) + ] + |) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_call_return : + M.IsFunction "revm::handler::mainnet::execution::call_return" call_return. + + (* + pub fn insert_call_outcome( + context: &mut Context, + frame: &mut Frame, + shared_memory: &mut SharedMemory, + outcome: CallOutcome, + ) -> Result<(), EVMError> { + context.evm.take_error()?; + frame + .frame_data_mut() + .interpreter + .insert_call_outcome(shared_memory, outcome); + Ok(()) + } + *) + Definition insert_call_outcome (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ EXT; DB ], [ context; frame; shared_memory; outcome ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let shared_memory := M.alloc (| shared_memory |) in + let outcome := M.alloc (| outcome |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::inner_evm_context::InnerEvmContext") + [ DB ], + "take_error", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "insert_call_outcome", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::Frame", + "frame_data_mut", + [] + |), + [ M.read (| frame |) ] + |), + "revm::frame::FrameData", + "interpreter" + |); + M.read (| shared_memory |); + M.read (| outcome |) + ] + |) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_insert_call_outcome : + M.IsFunction "revm::handler::mainnet::execution::insert_call_outcome" insert_call_outcome. + + (* + pub fn create( + context: &mut Context, + inputs: Box, + ) -> Result> { + context.evm.make_create_frame(SPEC::SPEC_ID, &inputs) + } + *) + Definition create (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context; inputs ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "make_create_frame", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| M.get_constant (| "revm_primitives::specification::Spec::SPEC_ID" |) |); + M.read (| inputs |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_create : M.IsFunction "revm::handler::mainnet::execution::create" create. + + (* + pub fn create_return( + context: &mut Context, + frame: Box, + mut interpreter_result: InterpreterResult, + ) -> Result> { + context.evm.create_return::( + &mut interpreter_result, + frame.created_address, + frame.frame_data.checkpoint, + ); + Ok(CreateOutcome::new( + interpreter_result, + Some(frame.created_address), + )) + } + *) + Definition create_return (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context; frame; interpreter_result ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let interpreter_result := M.alloc (| interpreter_result |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "create_return", + [ SPEC ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |); + interpreter_result; + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| frame |), + "revm::frame::CreateFrame", + "created_address" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| frame |), + "revm::frame::CreateFrame", + "frame_data" + |), + "revm::frame::FrameData", + "checkpoint" + |) + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "new", + [] + |), + [ + M.read (| interpreter_result |); + Value.StructTuple + "core::option::Option::Some" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| frame |), + "revm::frame::CreateFrame", + "created_address" + |) + |) + ] + ] + |) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_create_return : + M.IsFunction "revm::handler::mainnet::execution::create_return" create_return. + + (* + pub fn insert_create_outcome( + context: &mut Context, + frame: &mut Frame, + outcome: CreateOutcome, + ) -> Result<(), EVMError> { + context.evm.take_error()?; + frame + .frame_data_mut() + .interpreter + .insert_create_outcome(outcome); + Ok(()) + } + *) + Definition insert_create_outcome (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ EXT; DB ], [ context; frame; outcome ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let outcome := M.alloc (| outcome |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::inner_evm_context::InnerEvmContext") + [ DB ], + "take_error", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "insert_create_outcome", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::Frame", + "frame_data_mut", + [] + |), + [ M.read (| frame |) ] + |), + "revm::frame::FrameData", + "interpreter" + |); + M.read (| outcome |) + ] + |) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_insert_create_outcome : + M.IsFunction + "revm::handler::mainnet::execution::insert_create_outcome" + insert_create_outcome. + + (* + pub fn eofcreate( + context: &mut Context, + inputs: Box, + ) -> Result> { + context.evm.make_eofcreate_frame(SPEC::SPEC_ID, &inputs) + } + *) + Definition eofcreate (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context; inputs ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "make_eofcreate_frame", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |); + M.read (| M.get_constant (| "revm_primitives::specification::Spec::SPEC_ID" |) |); + M.read (| inputs |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_eofcreate : + M.IsFunction "revm::handler::mainnet::execution::eofcreate" eofcreate. + + (* + pub fn eofcreate_return( + context: &mut Context, + frame: Box, + mut interpreter_result: InterpreterResult, + ) -> Result> { + context.evm.eofcreate_return::( + &mut interpreter_result, + frame.created_address, + frame.frame_data.checkpoint, + ); + Ok(EOFCreateOutcome::new( + interpreter_result, + frame.created_address, + frame.return_memory_range, + )) + } + *) + Definition eofcreate_return (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context; frame; interpreter_result ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let interpreter_result := M.alloc (| interpreter_result |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "eofcreate_return", + [ SPEC ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |); + interpreter_result; + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| frame |), + "revm::frame::EOFCreateFrame", + "created_address" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| frame |), + "revm::frame::EOFCreateFrame", + "frame_data" + |), + "revm::frame::FrameData", + "checkpoint" + |) + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + "new", + [] + |), + [ + M.read (| interpreter_result |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| frame |), + "revm::frame::EOFCreateFrame", + "created_address" + |) + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| frame |), + "revm::frame::EOFCreateFrame", + "return_memory_range" + |) + |) + ] + |) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_eofcreate_return : + M.IsFunction "revm::handler::mainnet::execution::eofcreate_return" eofcreate_return. + + (* + pub fn insert_eofcreate_outcome( + context: &mut Context, + frame: &mut Frame, + outcome: EOFCreateOutcome, + ) -> Result<(), EVMError> { + core::mem::replace(&mut context.evm.error, Ok(()))?; + frame + .frame_data_mut() + .interpreter + .insert_eofcreate_outcome(outcome); + Ok(()) + } + *) + Definition insert_eofcreate_outcome (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ EXT; DB ], [ context; frame; outcome ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let frame := M.alloc (| frame |) in + let outcome := M.alloc (| outcome |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_function (| + "core::mem::replace", + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "error" + |); + Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "insert_eofcreate_outcome", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::Frame", + "frame_data_mut", + [] + |), + [ M.read (| frame |) ] + |), + "revm::frame::FrameData", + "interpreter" + |); + M.read (| outcome |) + ] + |) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_insert_eofcreate_outcome : + M.IsFunction + "revm::handler::mainnet::execution::insert_eofcreate_outcome" + insert_eofcreate_outcome. + End execution. + End mainnet. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/post_execution.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/post_execution.md new file mode 100644 index 00000000..e173e00c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/post_execution.md @@ -0,0 +1,1323 @@ +# ๐Ÿ“ post_execution.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler/mainnet/post_execution.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + Module mainnet. + Module post_execution. + (* + pub fn end( + _context: &mut Context, + evm_output: Result>, + ) -> Result> { + evm_output + } + *) + Definition end_ (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ EXT; DB ], [ _context; evm_output ] => + ltac:(M.monadic + (let _context := M.alloc (| _context |) in + let evm_output := M.alloc (| evm_output |) in + M.read (| evm_output |))) + | _, _ => M.impossible + end. + + Axiom Function_end_ : M.IsFunction "revm::handler::mainnet::post_execution::end" end_. + + (* + pub fn clear(context: &mut Context) { + // clear error and journaled state. + let _ = context.evm.take_error(); + context.evm.inner.journaled_state.clear(); + } + *) + Definition clear (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ EXT; DB ], [ context ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "revm::context::inner_evm_context::InnerEvmContext") [ DB ], + "take_error", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "clear", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_clear : M.IsFunction "revm::handler::mainnet::post_execution::clear" clear. + + (* + pub fn reward_beneficiary( + context: &mut Context, + gas: &Gas, + ) -> Result<(), EVMError> { + let beneficiary = context.evm.env.block.coinbase; + let effective_gas_price = context.evm.env.effective_gas_price(); + + // transfer fee to coinbase/beneficiary. + // EIP-1559 discard basefee for coinbase transfer. Basefee amount of gas is discarded. + let coinbase_gas_price = if SPEC::enabled(LONDON) { + effective_gas_price.saturating_sub(context.evm.env.block.basefee) + } else { + effective_gas_price + }; + + let (coinbase_account, _) = context + .evm + .inner + .journaled_state + .load_account(beneficiary, &mut context.evm.inner.db)?; + + coinbase_account.mark_touch(); + coinbase_account.info.balance = coinbase_account + .info + .balance + .saturating_add(coinbase_gas_price * U256::from(gas.spent() - gas.refunded() as u64)); + + Ok(()) + } + *) + Definition reward_beneficiary (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context; gas ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let gas := M.alloc (| gas |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ beneficiary := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "coinbase" + |) + |) in + let~ effective_gas_price := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "effective_gas_price", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |) + ] + |) + |) in + let~ coinbase_gas_price := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::LONDON" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "saturating_sub", + [] + |), + [ + M.read (| effective_gas_price |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "basefee" + |) + |) + ] + |) + |))); + fun ฮณ => ltac:(M.monadic effective_gas_price) + ] + |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| beneficiary |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let coinbase_account := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "mark_touch", + [] + |), + [ M.read (| coinbase_account |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| coinbase_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "saturating_add", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| coinbase_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Mul", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "mul", + [] + |), + [ + M.read (| coinbase_gas_price |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + BinOp.Wrap.sub + Integer.U64 + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "spent", + [] + |), + [ M.read (| gas |) ] + |)) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ M.read (| gas |) ] + |))) + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_reward_beneficiary : + M.IsFunction + "revm::handler::mainnet::post_execution::reward_beneficiary" + reward_beneficiary. + + (* + pub fn reimburse_caller( + context: &mut Context, + gas: &Gas, + ) -> Result<(), EVMError> { + let caller = context.evm.env.tx.caller; + let effective_gas_price = context.evm.env.effective_gas_price(); + + // return balance of not spend gas. + let (caller_account, _) = context + .evm + .inner + .journaled_state + .load_account(caller, &mut context.evm.inner.db)?; + + caller_account.info.balance = caller_account + .info + .balance + .saturating_add(effective_gas_price * U256::from(gas.remaining() + gas.refunded() as u64)); + + Ok(()) + } + *) + Definition reimburse_caller (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context; gas ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let gas := M.alloc (| gas |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ caller := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "caller" + |) + |) in + let~ effective_gas_price := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "effective_gas_price", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |) + ] + |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| caller |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let caller_account := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| caller_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "saturating_add", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| caller_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::Mul", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "mul", + [] + |), + [ + M.read (| effective_gas_price |); + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + BinOp.Wrap.add + Integer.U64 + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ M.read (| gas |) ] + |)) + (M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ M.read (| gas |) ] + |))) + ] + |) + ] + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_reimburse_caller : + M.IsFunction "revm::handler::mainnet::post_execution::reimburse_caller" reimburse_caller. + + (* + pub fn output( + context: &mut Context, + result: FrameResult, + ) -> Result> { + context.evm.take_error()?; + // used gas with refund calculated. + let gas_refunded = result.gas().refunded() as u64; + let final_gas_used = result.gas().spent() - gas_refunded; + let output = result.output(); + let instruction_result = result.into_interpreter_result(); + + // reset journal and return present state. + let (state, logs) = context.evm.journaled_state.finalize(); + + let result = match instruction_result.result.into() { + SuccessOrHalt::Success(reason) => ExecutionResult::Success { + reason, + gas_used: final_gas_used, + gas_refunded, + logs, + output, + }, + SuccessOrHalt::Revert => ExecutionResult::Revert { + gas_used: final_gas_used, + output: output.into_data(), + }, + SuccessOrHalt::Halt(reason) => ExecutionResult::Halt { + reason, + gas_used: final_gas_used, + }, + // Only two internal return flags. + flag @ (SuccessOrHalt::FatalExternalError + | SuccessOrHalt::InternalContinue + | SuccessOrHalt::InternalCallOrCreate) => { + panic!( + "Encountered unexpected internal return flag: {:?} with instruction result: {:?}", + flag, instruction_result + ) + } + }; + + Ok(ResultAndState { result, state }) + } + *) + Definition output (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ EXT; DB ], [ context; result ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + let result := M.alloc (| result |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::inner_evm_context::InnerEvmContext") + [ DB ], + "take_error", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_primitives::result::ResultAndState"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ gas_refunded := + M.alloc (| + M.rust_cast + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameResult", + "gas", + [] + |), + [ result ] + |) + ] + |)) + |) in + let~ final_gas_used := + M.alloc (| + BinOp.Wrap.sub + Integer.U64 + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "spent", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameResult", + "gas", + [] + |), + [ result ] + |) + ] + |)) + (M.read (| gas_refunded |)) + |) in + let~ output := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameResult", + "output", + [] + |), + [ result ] + |) + |) in + let~ instruction_result := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::FrameResult", + "into_interpreter_result", + [] + |), + [ M.read (| result |) ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "finalize", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let state := M.copy (| ฮณ0_0 |) in + let logs := M.copy (| ฮณ0_1 |) in + let~ result := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path + "revm_interpreter::instruction_result::InstructionResult", + [ + Ty.path + "revm_interpreter::instruction_result::SuccessOrHalt" + ], + "into", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + instruction_result, + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Success", + 0 + |) in + let reason := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructRecord + "revm_primitives::result::ExecutionResult::Success" + [ + ("reason", M.read (| reason |)); + ("gas_used", M.read (| final_gas_used |)); + ("gas_refunded", M.read (| gas_refunded |)); + ("logs", M.read (| logs |)); + ("output", M.read (| output |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Revert" + |) in + M.alloc (| + Value.StructRecord + "revm_primitives::result::ExecutionResult::Revert" + [ + ("gas_used", M.read (| final_gas_used |)); + ("output", + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::result::Output", + "into_data", + [] + |), + [ M.read (| output |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::Halt", + 0 + |) in + let reason := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.StructRecord + "revm_primitives::result::ExecutionResult::Halt" + [ + ("reason", M.read (| reason |)); + ("gas_used", M.read (| final_gas_used |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let flag := M.copy (| ฮณ |) in + M.find_or_pattern (| + ฮณ, + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::FatalExternalError" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::InternalContinue" + |) in + Value.Tuple [])); + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "revm_interpreter::instruction_result::SuccessOrHalt::InternalCallOrCreate" + |) in + Value.Tuple [])) + ], + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [] => + M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| + "core::panicking::panic_fmt", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| + Value.String + "Encountered unexpected internal return flag: " + |); + M.read (| + Value.String + " with instruction result: " + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_debug", + [ + Ty.path + "revm_interpreter::instruction_result::SuccessOrHalt" + ] + |), + [ flag ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "core::fmt::rt::Argument", + "new_debug", + [ + Ty.path + "revm_interpreter::interpreter::InterpreterResult" + ] + |), + [ instruction_result ] + |) + ] + |)) + ] + |) + ] + |) + |) + |) + | _ => M.impossible (||) + end)) + |))) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructRecord + "revm_primitives::result::ResultAndState" + [ ("result", M.read (| result |)); ("state", M.read (| state |)) ] + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_output : M.IsFunction "revm::handler::mainnet::post_execution::output" output. + End post_execution. + End mainnet. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/pre_execution.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/pre_execution.md new file mode 100644 index 00000000..b5049a4e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/pre_execution.md @@ -0,0 +1,891 @@ +# ๐Ÿ“ pre_execution.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler/mainnet/pre_execution.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + Module mainnet. + Module pre_execution. + (* + pub fn load_precompiles() -> ContextPrecompiles { + Precompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)) + .clone() + .into() + } + *) + Definition load_precompiles (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; DB ], [] => + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "revm_precompile::Precompiles", + [ Ty.apply (Ty.path "revm::context::context_precompiles::ContextPrecompiles") [ DB ] + ], + "into", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_precompile::Precompiles", + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::Precompiles", + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_precompile::PrecompileSpecId", + "from_spec_id", + [] + |), + [ + M.read (| + M.get_constant (| "revm_primitives::specification::Spec::SPEC_ID" |) + |) + ] + |) + ] + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Function_load_precompiles : + M.IsFunction "revm::handler::mainnet::pre_execution::load_precompiles" load_precompiles. + + (* + pub fn load_accounts( + context: &mut Context, + ) -> Result<(), EVMError> { + // set journaling state flag. + context.evm.journaled_state.set_spec_id(SPEC::SPEC_ID); + + // load coinbase + // EIP-3651: Warm COINBASE. Starts the `COINBASE` address warm + if SPEC::enabled(SHANGHAI) { + context.evm.inner.journaled_state.initial_account_load( + context.evm.inner.env.block.coinbase, + &[], + &mut context.evm.inner.db, + )?; + } + + context.evm.load_access_list()?; + Ok(()) + } + *) + Definition load_accounts (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "set_spec_id", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply (Ty.path "revm::context::evm_context::EvmContext") [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.get_constant (| "revm_primitives::specification::Spec::SPEC_ID" |) + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::SHANGHAI" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "initial_account_load", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "block" + |), + "revm_primitives::env::BlockEnv", + "coinbase" + |) + |); + (* Unsize *) + M.pointer_coercion (M.alloc (| Value.Array [] |)); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::context::inner_evm_context::InnerEvmContext") + [ DB ], + "load_access_list", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_load_accounts : + M.IsFunction "revm::handler::mainnet::pre_execution::load_accounts" load_accounts. + + (* + pub fn deduct_caller_inner(caller_account: &mut Account, env: &Env) { + // Subtract gas costs from the caller's account. + // We need to saturate the gas cost to prevent underflow in case that `disable_balance_check` is enabled. + let mut gas_cost = U256::from(env.tx.gas_limit).saturating_mul(env.effective_gas_price()); + + // EIP-4844 + if SPEC::enabled(CANCUN) { + let data_fee = env.calc_data_fee().expect("already checked"); + gas_cost = gas_cost.saturating_add(data_fee); + } + + // set new caller account balance. + caller_account.info.balance = caller_account.info.balance.saturating_sub(gas_cost); + + // bump the nonce for calls. Nonce for CREATE will be bumped in `handle_create`. + if matches!(env.tx.transact_to, TransactTo::Call(_)) { + // Nonce is already checked + caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); + } + + // touch account so we know it is changed. + caller_account.mark_touch(); + } + *) + Definition deduct_caller_inner (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC ], [ caller_account; env ] => + ltac:(M.monadic + (let caller_account := M.alloc (| caller_account |) in + let env := M.alloc (| env |) in + M.read (| + let~ gas_cost := + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "saturating_mul", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "from", + [ Ty.path "u64" ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_limit" + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "effective_gas_price", + [] + |), + [ M.read (| env |) ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm_primitives::specification::Spec", + SPEC, + [], + "enabled", + [] + |), + [ + Value.StructTuple + "revm_primitives::specification::SpecId::CANCUN" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ data_fee := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "calc_data_fee", + [] + |), + [ M.read (| env |) ] + |); + M.read (| Value.String "already checked" |) + ] + |) + |) in + let~ _ := + M.write (| + gas_cost, + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "saturating_add", + [] + |), + [ M.read (| gas_cost |); M.read (| data_fee |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| caller_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |), + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "saturating_sub", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| caller_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |); + M.read (| gas_cost |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.match_operator (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "transact_to" + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_primitives::env::TransactTo::Call", + 0 + |) in + M.alloc (| Value.Bool true |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Bool false |))) + ] + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| caller_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "saturating_add", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| caller_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + |); + Value.Integer 1 + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "mark_touch", + [] + |), + [ M.read (| caller_account |) ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_deduct_caller_inner : + M.IsFunction + "revm::handler::mainnet::pre_execution::deduct_caller_inner" + deduct_caller_inner. + + (* + pub fn deduct_caller( + context: &mut Context, + ) -> Result<(), EVMError> { + // load caller's account. + let (caller_account, _) = context + .evm + .inner + .journaled_state + .load_account(context.evm.inner.env.tx.caller, &mut context.evm.inner.db)?; + + // deduct gas cost from caller's account. + deduct_caller_inner::(caller_account, &context.evm.inner.env); + + Ok(()) + } + *) + Definition deduct_caller (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "caller" + |) + |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let caller_account := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm::handler::mainnet::pre_execution::deduct_caller_inner", + [ SPEC ] + |), + [ + M.read (| caller_account |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |) + ] + |) + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_deduct_caller : + M.IsFunction "revm::handler::mainnet::pre_execution::deduct_caller" deduct_caller. + End pre_execution. + End mainnet. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/validation.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/validation.md new file mode 100644 index 00000000..c12ec9a2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/mainnet/validation.md @@ -0,0 +1,761 @@ +# ๐Ÿ“ validation.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler/mainnet/validation.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + Module mainnet. + Module validation. + (* + pub fn validate_env(env: &Env) -> Result<(), EVMError> { + // Important: validate block before tx. + env.validate_block_env::()?; + env.validate_tx::()?; + Ok(()) + } + *) + Definition validate_env (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; DB ], [ env ] => + ltac:(M.monadic + (let env := M.alloc (| env |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.path "revm_primitives::result::InvalidHeader" ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "validate_block_env", + [ SPEC ] + |), + [ M.read (| env |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "revm_primitives::result::InvalidHeader" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ Ty.tuple []; Ty.path "revm_primitives::result::InvalidTransaction" + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "validate_tx", + [ SPEC ] + |), + [ M.read (| env |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.path "revm_primitives::result::InvalidTransaction" + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_validate_env : + M.IsFunction "revm::handler::mainnet::validation::validate_env" validate_env. + + (* + pub fn validate_tx_against_state( + context: &mut Context, + ) -> Result<(), EVMError> { + // load acc + let tx_caller = context.evm.env.tx.caller; + let (caller_account, _) = context + .evm + .inner + .journaled_state + .load_account(tx_caller, &mut context.evm.inner.db)?; + + context + .evm + .inner + .env + .validate_tx_against_state::(caller_account) + .map_err(EVMError::Transaction)?; + + Ok(()) + } + *) + Definition validate_tx_against_state (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; EXT; DB ], [ context ] => + ltac:(M.monadic + (let context := M.alloc (| context |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ tx_caller := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "caller" + |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |); + M.read (| tx_caller |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "db" + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let caller_account := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.path "revm_primitives::result::InvalidTransaction" + ], + "map_err", + [ + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ]; + Ty.function + [ Ty.path "revm_primitives::result::InvalidTransaction" + ] + (Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::Env", + "validate_tx_against_state", + [ SPEC ] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| context |), + "revm::context::Context", + "evm" + |), + "revm::context::evm_context::EvmContext", + "inner" + |), + "revm::context::inner_evm_context::InnerEvmContext", + "env" + |) + |); + M.read (| caller_account |) + ] + |); + M.constructor_as_closure + "revm_primitives::result::EVMError::Transaction" + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_validate_tx_against_state : + M.IsFunction + "revm::handler::mainnet::validation::validate_tx_against_state" + validate_tx_against_state. + + (* + pub fn validate_initial_tx_gas( + env: &Env, + ) -> Result> { + let input = &env.tx.data; + let is_create = env.tx.transact_to.is_create(); + let access_list = &env.tx.access_list; + let initcodes = &env.tx.eof_initcodes; + + let initial_gas_spend = + gas::validate_initial_tx_gas(SPEC::SPEC_ID, input, is_create, access_list, initcodes); + + // Additional check to see if limit is big enough to cover initial gas. + if initial_gas_spend > env.tx.gas_limit { + return Err(InvalidTransaction::CallGasCostMoreThanGasLimit.into()); + } + Ok(initial_gas_spend) + } + *) + Definition validate_initial_tx_gas (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ SPEC; DB ], [ env ] => + ltac:(M.monadic + (let env := M.alloc (| env |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ input := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "data" + |) + |) in + let~ is_create := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::env::TransactTo", + "is_create", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "transact_to" + |) + ] + |) + |) in + let~ access_list := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "access_list" + |) + |) in + let~ initcodes := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "eof_initcodes" + |) + |) in + let~ initial_gas_spend := + M.alloc (| + M.call_closure (| + M.get_function (| + "revm_interpreter::gas::calc::validate_initial_tx_gas", + [] + |), + [ + M.read (| + M.get_constant (| "revm_primitives::specification::Spec::SPEC_ID" |) + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "bytes::bytes::Bytes", + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ M.read (| input |) ] + |) + ] + |); + M.read (| is_create |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "ruint::Uint"; Ty.path "alloc::alloc::Global" ] + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ M.read (| access_list |) ] + |); + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "alloy_primitives::bytes_::Bytes"; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ M.read (| initcodes |) ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.gt + (M.read (| initial_gas_spend |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| env |), + "revm_primitives::env::Env", + "tx" + |), + "revm_primitives::env::TxEnv", + "gas_limit" + |) + |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "revm_primitives::result::InvalidTransaction", + [ + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + "into", + [] + |), + [ + Value.StructTuple + "revm_primitives::result::InvalidTransaction::CallGasCostMoreThanGasLimit" + [] + ] + |) + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ M.read (| initial_gas_spend |) ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Function_validate_initial_tx_gas : + M.IsFunction + "revm::handler::mainnet::validation::validate_initial_tx_gas" + validate_initial_tx_gas. + End validation. + End mainnet. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/register.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/register.md new file mode 100644 index 00000000..cd4d69c7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/handler/register.md @@ -0,0 +1,184 @@ +# ๐Ÿ“ register.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/handler/register.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module handler. + Module register. + Axiom EvmHandler : + forall (EXT DB : Ty.t), + (Ty.apply (Ty.path "revm::handler::register::EvmHandler") [ EXT; DB ]) = + (Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ]). + + Axiom HandleRegister : + forall (EXT DB : Ty.t), + (Ty.apply (Ty.path "revm::handler::register::HandleRegister") [ EXT; DB ]) = + (Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ] + ] + ] + (Ty.tuple [])). + + Axiom HandleRegisterBox : + forall (EXT DB : Ty.t), + (Ty.apply (Ty.path "revm::handler::register::HandleRegisterBox") [ EXT; DB ]) = + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]). + + (* + Enum HandleRegisters + { + ty_params := [ "EXT"; "DB" ]; + variants := + [ + { + name := "Plain"; + item := + StructTuple + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ] + ] + ] + (Ty.tuple []) + ]; + discriminant := None; + }; + { + name := "Box"; + item := + StructTuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_revm_handler_register_HandleRegisters_EXT_DB. + Definition Self (EXT DB : Ty.t) : Ty.t := + Ty.apply (Ty.path "revm::handler::register::HandleRegisters") [ EXT; DB ]. + + (* + pub fn register(&self, handler: &mut EvmHandler<'_, EXT, DB>) { + match self { + HandleRegisters::Plain(f) => f(handler), + HandleRegisters::Box(f) => f(handler), + } + } + *) + Definition register (EXT DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self EXT DB in + match ฯ„, ฮฑ with + | [], [ self; handler ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let handler := M.alloc (| handler |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::handler::register::HandleRegisters::Plain", + 0 + |) in + let f := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| M.read (| M.read (| f |) |), [ M.read (| handler |) ] |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::handler::register::HandleRegisters::Box", + 0 + |) in + let f := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ] + ] + ] + ], + "call", + [] + |), + [ M.read (| f |); Value.Tuple [ M.read (| handler |) ] ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_register : + forall (EXT DB : Ty.t), + M.IsAssociatedFunction (Self EXT DB) "register" (register EXT DB). + End Impl_revm_handler_register_HandleRegisters_EXT_DB. + End register. +End handler. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector.md new file mode 100644 index 00000000..d723626f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector.md @@ -0,0 +1,779 @@ +# ๐Ÿ“ inspector.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/inspector.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module inspector. + (* Trait *) + Module Inspector. + Definition initialize_interp (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.read (| + M.match_operator (| + interp, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + context, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_initialize_interp : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "initialize_interp" (initialize_interp DB). + Definition step (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.read (| + M.match_operator (| + interp, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + context, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_step : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "step" (step DB). + Definition step_end (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.read (| + M.match_operator (| + interp, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + context, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_step_end : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "step_end" (step_end DB). + Definition log (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; context; log ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let log := M.alloc (| log |) in + M.read (| + M.match_operator (| + context, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + log, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_log : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "log" (log DB). + Definition call (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.read (| + M.match_operator (| + context, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + inputs, + [ + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_call : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "call" (call DB). + Definition call_end (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.read (| + M.match_operator (| + context, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| inputs, [ fun ฮณ => ltac:(M.monadic outcome) ] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_call_end : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "call_end" (call_end DB). + Definition create (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.read (| + M.match_operator (| + context, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + inputs, + [ + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_create : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "create" (create DB). + Definition create_end (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.read (| + M.match_operator (| + context, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| inputs, [ fun ฮณ => ltac:(M.monadic outcome) ] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_create_end : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "create_end" (create_end DB). + Definition eofcreate (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.read (| + M.match_operator (| + context, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + inputs, + [ + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_eofcreate : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "eofcreate" (eofcreate DB). + Definition eofcreate_end (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.read (| + M.match_operator (| + context, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| inputs, [ fun ฮณ => ltac:(M.monadic outcome) ] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_eofcreate_end : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "eofcreate_end" (eofcreate_end DB). + Definition selfdestruct (DB Self : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; contract; target; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let contract := M.alloc (| contract |) in + let target := M.alloc (| target |) in + let value := M.alloc (| value |) in + M.read (| + M.match_operator (| + contract, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + target, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + value, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom ProvidedMethod_selfdestruct : + forall (DB : Ty.t), + M.IsProvidedMethod "revm::inspector::Inspector" "selfdestruct" (selfdestruct DB). + End Inspector. + + Module underscore. + Module Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_where_revm_inspector_Inspector_T_DB_where_core_marker_Sized_T_DB_for_ref_mut_T. + Definition Self (DB T : Ty.t) : Ty.t := Ty.apply (Ty.path "&mut") [ T ]. + + (* #[auto_impl(&mut, Box)] *) + Definition initialize_interp (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + T, + [ DB ], + "initialize_interp", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| interp |); M.read (| context |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition step (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "step", [] |), + [ M.read (| M.read (| self |) |); M.read (| interp |); M.read (| context |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition step_end (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "step_end", [] |), + [ M.read (| M.read (| self |) |); M.read (| interp |); M.read (| context |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition log (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; log ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let log := M.alloc (| log |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "log", [] |), + [ M.read (| M.read (| self |) |); M.read (| context |); M.read (| log |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition call (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "call", [] |), + [ M.read (| M.read (| self |) |); M.read (| context |); M.read (| inputs |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition call_end (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "call_end", [] |), + [ + M.read (| M.read (| self |) |); + M.read (| context |); + M.read (| inputs |); + M.read (| outcome |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition create (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "create", [] |), + [ M.read (| M.read (| self |) |); M.read (| context |); M.read (| inputs |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition create_end (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "create_end", [] |), + [ + M.read (| M.read (| self |) |); + M.read (| context |); + M.read (| inputs |); + M.read (| outcome |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition eofcreate (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "eofcreate", [] |), + [ M.read (| M.read (| self |) |); M.read (| context |); M.read (| inputs |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition eofcreate_end (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "eofcreate_end", [] |), + [ + M.read (| M.read (| self |) |); + M.read (| context |); + M.read (| inputs |); + M.read (| outcome |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition selfdestruct (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; contract; target; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let contract := M.alloc (| contract |) in + let target := M.alloc (| target |) in + let value := M.alloc (| value |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "selfdestruct", [] |), + [ + M.read (| M.read (| self |) |); + M.read (| contract |); + M.read (| target |); + M.read (| value |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB T : Ty.t), + M.IsTraitInstance + "revm::inspector::Inspector" + (Self DB T) + (* Trait polymorphic types *) [ (* DB *) DB ] + (* Instance *) + [ + ("initialize_interp", InstanceField.Method (initialize_interp DB T)); + ("step", InstanceField.Method (step DB T)); + ("step_end", InstanceField.Method (step_end DB T)); + ("log", InstanceField.Method (log DB T)); + ("call", InstanceField.Method (call DB T)); + ("call_end", InstanceField.Method (call_end DB T)); + ("create", InstanceField.Method (create DB T)); + ("create_end", InstanceField.Method (create_end DB T)); + ("eofcreate", InstanceField.Method (eofcreate DB T)); + ("eofcreate_end", InstanceField.Method (eofcreate_end DB T)); + ("selfdestruct", InstanceField.Method (selfdestruct DB T)) + ]. + End Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_where_revm_inspector_Inspector_T_DB_where_core_marker_Sized_T_DB_for_ref_mut_T. + Module Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_where_revm_inspector_Inspector_T_DB_where_core_marker_Sized_T_DB_for_alloc_boxed_Box_T_alloc_alloc_Global. + Definition Self (DB T : Ty.t) : Ty.t := + Ty.apply (Ty.path "alloc::boxed::Box") [ T; Ty.path "alloc::alloc::Global" ]. + + (* #[auto_impl(&mut, Box)] *) + Definition initialize_interp (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + T, + [ DB ], + "initialize_interp", + [] + |), + [ M.read (| M.read (| self |) |); M.read (| interp |); M.read (| context |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition step (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "step", [] |), + [ M.read (| M.read (| self |) |); M.read (| interp |); M.read (| context |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition step_end (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "step_end", [] |), + [ M.read (| M.read (| self |) |); M.read (| interp |); M.read (| context |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition log (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; log ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let log := M.alloc (| log |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "log", [] |), + [ M.read (| M.read (| self |) |); M.read (| context |); M.read (| log |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition call (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "call", [] |), + [ M.read (| M.read (| self |) |); M.read (| context |); M.read (| inputs |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition call_end (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "call_end", [] |), + [ + M.read (| M.read (| self |) |); + M.read (| context |); + M.read (| inputs |); + M.read (| outcome |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition create (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "create", [] |), + [ M.read (| M.read (| self |) |); M.read (| context |); M.read (| inputs |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition create_end (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "create_end", [] |), + [ + M.read (| M.read (| self |) |); + M.read (| context |); + M.read (| inputs |); + M.read (| outcome |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition eofcreate (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "eofcreate", [] |), + [ M.read (| M.read (| self |) |); M.read (| context |); M.read (| inputs |) ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition eofcreate_end (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "eofcreate_end", [] |), + [ + M.read (| M.read (| self |) |); + M.read (| context |); + M.read (| inputs |); + M.read (| outcome |) + ] + |))) + | _, _ => M.impossible + end. + + (* #[auto_impl(&mut, Box)] *) + Definition selfdestruct (DB T : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB T in + match ฯ„, ฮฑ with + | [], [ self; contract; target; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let contract := M.alloc (| contract |) in + let target := M.alloc (| target |) in + let value := M.alloc (| value |) in + M.call_closure (| + M.get_trait_method (| "revm::inspector::Inspector", T, [ DB ], "selfdestruct", [] |), + [ + M.read (| M.read (| self |) |); + M.read (| contract |); + M.read (| target |); + M.read (| value |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB T : Ty.t), + M.IsTraitInstance + "revm::inspector::Inspector" + (Self DB T) + (* Trait polymorphic types *) [ (* DB *) DB ] + (* Instance *) + [ + ("initialize_interp", InstanceField.Method (initialize_interp DB T)); + ("step", InstanceField.Method (step DB T)); + ("step_end", InstanceField.Method (step_end DB T)); + ("log", InstanceField.Method (log DB T)); + ("call", InstanceField.Method (call DB T)); + ("call_end", InstanceField.Method (call_end DB T)); + ("create", InstanceField.Method (create DB T)); + ("create_end", InstanceField.Method (create_end DB T)); + ("eofcreate", InstanceField.Method (eofcreate DB T)); + ("eofcreate_end", InstanceField.Method (eofcreate_end DB T)); + ("selfdestruct", InstanceField.Method (selfdestruct DB T)) + ]. + End Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_where_revm_inspector_Inspector_T_DB_where_core_marker_Sized_T_DB_for_alloc_boxed_Box_T_alloc_alloc_Global. + End underscore. + +End inspector. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/customprinter.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/customprinter.md new file mode 100644 index 00000000..d4d21b89 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/customprinter.md @@ -0,0 +1,1234 @@ +# ๐Ÿ“ customprinter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/inspector/customprinter.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module inspector. + Module customprinter. + (* StructRecord + { + name := "CustomPrintTracer"; + ty_params := []; + fields := [ ("gas_inspector", Ty.path "revm::inspector::gas::GasInspector") ]; + } *) + + Module Impl_core_clone_Clone_for_revm_inspector_customprinter_CustomPrintTracer. + Definition Self : Ty.t := Ty.path "revm::inspector::customprinter::CustomPrintTracer". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::inspector::customprinter::CustomPrintTracer" + [ + ("gas_inspector", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm::inspector::gas::GasInspector", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::customprinter::CustomPrintTracer", + "gas_inspector" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_inspector_customprinter_CustomPrintTracer. + + Module Impl_core_fmt_Debug_for_revm_inspector_customprinter_CustomPrintTracer. + Definition Self : Ty.t := Ty.path "revm::inspector::customprinter::CustomPrintTracer". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CustomPrintTracer" |); + M.read (| Value.String "gas_inspector" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::customprinter::CustomPrintTracer", + "gas_inspector" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_inspector_customprinter_CustomPrintTracer. + + Module Impl_core_default_Default_for_revm_inspector_customprinter_CustomPrintTracer. + Definition Self : Ty.t := Ty.path "revm::inspector::customprinter::CustomPrintTracer". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::inspector::customprinter::CustomPrintTracer" + [ + ("gas_inspector", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm::inspector::gas::GasInspector", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_inspector_customprinter_CustomPrintTracer. + + Module Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_DB_for_revm_inspector_customprinter_CustomPrintTracer. + Definition Self (DB : Ty.t) : Ty.t := + Ty.path "revm::inspector::customprinter::CustomPrintTracer". + + (* + fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.gas_inspector.initialize_interp(interp, context); + } + *) + Definition initialize_interp (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.path "revm::inspector::gas::GasInspector", + [ DB ], + "initialize_interp", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::customprinter::CustomPrintTracer", + "gas_inspector" + |); + M.read (| interp |); + M.read (| context |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + let opcode = interp.current_opcode(); + let name = OpCode::name_by_op(opcode); + + let gas_remaining = self.gas_inspector.gas_remaining(); + + let memory_size = interp.shared_memory.len(); + + println!( + "depth:{}, PC:{}, gas:{:#x}({}), OPCODE: {:?}({:?}) refund:{:#x}({}) Stack:{:?}, Data size:{}", + context.journaled_state.depth(), + interp.program_counter(), + gas_remaining, + gas_remaining, + name, + opcode, + interp.gas.refunded(), + interp.gas.refunded(), + interp.stack.data(), + memory_size, + ); + + self.gas_inspector.step(interp, context); + } + *) + Definition step (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.read (| + let~ opcode := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "current_opcode", + [] + |), + [ M.read (| interp |) ] + |) + |) in + let~ name := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::opcode::OpCode", + "name_by_op", + [] + |), + [ M.read (| opcode |) ] + |) + |) in + let~ gas_remaining := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::inspector::gas::GasInspector", + "gas_remaining", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::customprinter::CustomPrintTracer", + "gas_inspector" + |) + ] + |) + |) in + let~ memory_size := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::shared_memory::SharedMemory", + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interp |), + "revm_interpreter::interpreter::Interpreter", + "shared_memory" + |) + ] + |) + |) in + let~ _ := + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| "std::io::stdio::_print", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1_formatted", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| Value.String "depth:" |); + M.read (| Value.String ", PC:" |); + M.read (| Value.String ", gas:" |); + M.read (| Value.String "(" |); + M.read (| Value.String "), OPCODE: " |); + M.read (| Value.String "(" |); + M.read (| Value.String ") refund:" |); + M.read (| Value.String "(" |); + M.read (| Value.String ") Stack:" |); + M.read (| Value.String ", Data size:" |); + M.read (| Value.String " +" |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.path "u64" ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "depth", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB ], + [], + "deref", + [] + |), + [ M.read (| context |) ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |) + ] + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.path "usize" ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::Interpreter", + "program_counter", + [] + |), + [ M.read (| interp |) ] + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_lower_hex", + [ Ty.path "u64" ] + |), + [ gas_remaining ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.path "u64" ] + |), + [ gas_remaining ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.apply (Ty.path "&") [ Ty.path "str" ] ] + |), + [ name ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "u8" ] + |), + [ opcode ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_lower_hex", + [ Ty.path "i64" ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interp |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + ] + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.path "i64" ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "refunded", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interp |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + ] + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "ruint::Uint"; + Ty.path "alloc::alloc::Global" + ] + ] + ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::interpreter::stack::Stack", + "data", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interp |), + "revm_interpreter::interpreter::Interpreter", + "stack" + |) + ] + |) + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_display", + [ Ty.path "usize" ] + |), + [ memory_size ] + |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 0; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 0; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 1; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 0; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 2; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 4; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 3; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 0; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 4; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 0; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 5; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 0; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 6; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 4; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 7; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 0; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 8; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 0; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Placeholder", + "new", + [] + |), + [ + Value.Integer 9; + Value.UnicodeChar 32; + Value.StructTuple "core::fmt::rt::Alignment::Unknown" []; + Value.Integer 0; + Value.StructTuple "core::fmt::rt::Count::Implied" []; + Value.StructTuple "core::fmt::rt::Count::Implied" [] + ] + |) + ] + |)); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::UnsafeArg", + "new", + [] + |), + [] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.path "revm::inspector::gas::GasInspector", + [ DB ], + "step", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::customprinter::CustomPrintTracer", + "gas_inspector" + |); + M.read (| interp |); + M.read (| context |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.gas_inspector.step_end(interp, context); + } + *) + Definition step_end (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; interp; context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let context := M.alloc (| context |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.path "revm::inspector::gas::GasInspector", + [ DB ], + "step_end", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::customprinter::CustomPrintTracer", + "gas_inspector" + |); + M.read (| interp |); + M.read (| context |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn call_end( + &mut self, + context: &mut EvmContext, + inputs: &CallInputs, + outcome: CallOutcome, + ) -> CallOutcome { + self.gas_inspector.call_end(context, inputs, outcome) + } + *) + Definition call_end (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.path "revm::inspector::gas::GasInspector", + [ DB ], + "call_end", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::customprinter::CustomPrintTracer", + "gas_inspector" + |); + M.read (| context |); + M.read (| inputs |); + M.read (| outcome |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn create_end( + &mut self, + context: &mut EvmContext, + inputs: &CreateInputs, + outcome: CreateOutcome, + ) -> CreateOutcome { + self.gas_inspector.create_end(context, inputs, outcome) + } + *) + Definition create_end (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; context; inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let context := M.alloc (| context |) in + let inputs := M.alloc (| inputs |) in + let outcome := M.alloc (| outcome |) in + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.path "revm::inspector::gas::GasInspector", + [ DB ], + "create_end", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::customprinter::CustomPrintTracer", + "gas_inspector" + |); + M.read (| context |); + M.read (| inputs |); + M.read (| outcome |) + ] + |))) + | _, _ => M.impossible + end. + + (* + fn call( + &mut self, + _context: &mut EvmContext, + inputs: &mut CallInputs, + ) -> Option { + println!( + "SM Address: {:?}, caller:{:?},target:{:?} is_static:{:?}, transfer:{:?}, input_size:{:?}", + inputs.bytecode_address, + inputs.caller, + inputs.target_address, + inputs.is_static, + inputs.value, + inputs.input.len(), + ); + None + } + *) + Definition call (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; _context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _context := M.alloc (| _context |) in + let inputs := M.alloc (| inputs |) in + M.read (| + let~ _ := + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| "std::io::stdio::_print", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| Value.String "SM Address: " |); + M.read (| Value.String ", caller:" |); + M.read (| Value.String ",target:" |); + M.read (| Value.String " is_static:" |); + M.read (| Value.String ", transfer:" |); + M.read (| Value.String ", input_size:" |); + M.read (| Value.String " +" |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "bytecode_address" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "caller" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "target_address" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "bool" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "is_static" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallValue" + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "value" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "usize" ] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "bytes::bytes::Bytes", + "len", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.path "alloy_primitives::bytes_::Bytes", + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::call_inputs::CallInputs", + "input" + |) + ] + |) + ] + |) + |) + ] + |) + ] + |)) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn create( + &mut self, + _context: &mut EvmContext, + inputs: &mut CreateInputs, + ) -> Option { + println!( + "CREATE CALL: caller:{:?}, scheme:{:?}, value:{:?}, init_code:{:?}, gas:{:?}", + inputs.caller, inputs.scheme, inputs.value, inputs.init_code, inputs.gas_limit + ); + None + } + *) + Definition create (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; _context; inputs ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _context := M.alloc (| _context |) in + let inputs := M.alloc (| inputs |) in + M.read (| + let~ _ := + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| "std::io::stdio::_print", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| Value.String "CREATE CALL: caller:" |); + M.read (| Value.String ", scheme:" |); + M.read (| Value.String ", value:" |); + M.read (| Value.String ", init_code:" |); + M.read (| Value.String ", gas:" |); + M.read (| Value.String " +" |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "caller" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "revm_primitives::env::CreateScheme" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "scheme" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "ruint::Uint" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "value" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "alloy_primitives::bytes_::Bytes" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "init_code" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "u64" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| inputs |), + "revm_interpreter::interpreter_action::create_inputs::CreateInputs", + "gas_limit" + |) + ] + |) + ] + |)) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + M.alloc (| Value.StructTuple "core::option::Option::None" [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + println!( + "SELFDESTRUCT: contract: {:?}, refund target: {:?}, value {:?}", + contract, target, value + ); + } + *) + Definition selfdestruct (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; contract; target; value ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let contract := M.alloc (| contract |) in + let target := M.alloc (| target |) in + let value := M.alloc (| value |) in + M.read (| + let~ _ := + let~ _ := + M.alloc (| + M.call_closure (| + M.get_function (| "std::io::stdio::_print", [] |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Arguments", + "new_v1", + [] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.read (| Value.String "SELFDESTRUCT: contract: " |); + M.read (| Value.String ", refund target: " |); + M.read (| Value.String ", value " |); + M.read (| Value.String " +" |) + ] + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ contract ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ target ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::rt::Argument", + "new_debug", + [ Ty.path "ruint::Uint" ] + |), + [ value ] + |) + ] + |)) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "revm::inspector::Inspector" + (Self DB) + (* Trait polymorphic types *) [ (* DB *) DB ] + (* Instance *) + [ + ("initialize_interp", InstanceField.Method (initialize_interp DB)); + ("step", InstanceField.Method (step DB)); + ("step_end", InstanceField.Method (step_end DB)); + ("call_end", InstanceField.Method (call_end DB)); + ("create_end", InstanceField.Method (create_end DB)); + ("call", InstanceField.Method (call DB)); + ("create", InstanceField.Method (create DB)); + ("selfdestruct", InstanceField.Method (selfdestruct DB)) + ]. + End Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_DB_for_revm_inspector_customprinter_CustomPrintTracer. + End customprinter. +End inspector. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/gas.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/gas.md new file mode 100644 index 00000000..6b34d3f1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/gas.md @@ -0,0 +1,572 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/inspector/gas.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module inspector. + Module gas. + (* StructRecord + { + name := "GasInspector"; + ty_params := []; + fields := [ ("gas_remaining", Ty.path "u64"); ("last_gas_cost", Ty.path "u64") ]; + } *) + + Module Impl_core_clone_Clone_for_revm_inspector_gas_GasInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::gas::GasInspector". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_inspector_gas_GasInspector. + + Module Impl_core_marker_Copy_for_revm_inspector_gas_GasInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::gas::GasInspector". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_inspector_gas_GasInspector. + + Module Impl_core_fmt_Debug_for_revm_inspector_gas_GasInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::gas::GasInspector". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "GasInspector" |); + M.read (| Value.String "gas_remaining" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "gas_remaining" + |)); + M.read (| Value.String "last_gas_cost" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "last_gas_cost" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_inspector_gas_GasInspector. + + Module Impl_core_default_Default_for_revm_inspector_gas_GasInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::gas::GasInspector". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => + ltac:(M.monadic + (Value.StructRecord + "revm::inspector::gas::GasInspector" + [ + ("gas_remaining", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u64", + [], + "default", + [] + |), + [] + |)); + ("last_gas_cost", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "u64", + [], + "default", + [] + |), + [] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_inspector_gas_GasInspector. + + Module Impl_revm_inspector_gas_GasInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::gas::GasInspector". + + (* + pub fn gas_remaining(&self) -> u64 { + self.gas_remaining + } + *) + Definition gas_remaining (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "gas_remaining" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_gas_remaining : + M.IsAssociatedFunction Self "gas_remaining" gas_remaining. + + (* + pub fn last_gas_cost(&self) -> u64 { + self.last_gas_cost + } + *) + Definition last_gas_cost (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "last_gas_cost" + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_last_gas_cost : + M.IsAssociatedFunction Self "last_gas_cost" last_gas_cost. + End Impl_revm_inspector_gas_GasInspector. + + Module Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_DB_for_revm_inspector_gas_GasInspector. + Definition Self (DB : Ty.t) : Ty.t := Ty.path "revm::inspector::gas::GasInspector". + + (* + fn initialize_interp( + &mut self, + interp: &mut crate::interpreter::Interpreter, + _context: &mut EvmContext, + ) { + self.gas_remaining = interp.gas.limit(); + } + *) + Definition initialize_interp (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; interp; _context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let _context := M.alloc (| _context |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "gas_remaining" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "limit", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interp |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn step( + &mut self, + interp: &mut crate::interpreter::Interpreter, + _context: &mut EvmContext, + ) { + self.gas_remaining = interp.gas.remaining(); + } + *) + Definition step (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; interp; _context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let _context := M.alloc (| _context |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "gas_remaining" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interp |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn step_end( + &mut self, + interp: &mut crate::interpreter::Interpreter, + _context: &mut EvmContext, + ) { + let remaining = interp.gas.remaining(); + self.last_gas_cost = self.gas_remaining.saturating_sub(remaining); + self.gas_remaining = remaining; + } + *) + Definition step_end (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; interp; _context ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let interp := M.alloc (| interp |) in + let _context := M.alloc (| _context |) in + M.read (| + let~ remaining := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "remaining", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interp |), + "revm_interpreter::interpreter::Interpreter", + "gas" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "last_gas_cost" + |), + M.call_closure (| + M.get_associated_function (| Ty.path "u64", "saturating_sub", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "gas_remaining" + |) + |); + M.read (| remaining |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "gas_remaining" + |), + M.read (| remaining |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + (* + fn call_end( + &mut self, + _context: &mut EvmContext, + _inputs: &CallInputs, + mut outcome: CallOutcome, + ) -> CallOutcome { + if outcome.result.result.is_error() { + outcome.result.gas.spend_all(); + self.gas_remaining = 0; + } + outcome + } + *) + Definition call_end (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; _context; _inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _context := M.alloc (| _context |) in + let _inputs := M.alloc (| _inputs |) in + let outcome := M.alloc (| outcome |) in + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::instruction_result::InstructionResult", + "is_error", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + outcome, + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "spend_all", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + outcome, + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "gas_remaining" + |), + Value.Integer 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + outcome + |))) + | _, _ => M.impossible + end. + + (* + fn create_end( + &mut self, + _context: &mut EvmContext, + _inputs: &CreateInputs, + mut outcome: CreateOutcome, + ) -> CreateOutcome { + if outcome.result.result.is_error() { + outcome.result.gas.spend_all(); + self.gas_remaining = 0; + } + outcome + } + *) + Definition create_end (DB : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB in + match ฯ„, ฮฑ with + | [], [ self; _context; _inputs; outcome ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let _context := M.alloc (| _context |) in + let _inputs := M.alloc (| _inputs |) in + let outcome := M.alloc (| outcome |) in + M.read (| + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::instruction_result::InstructionResult", + "is_error", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + outcome, + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "result" + |) + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_interpreter::gas::Gas", + "spend_all", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + outcome, + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + "result" + |), + "revm_interpreter::interpreter::InterpreterResult", + "gas" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::inspector::gas::GasInspector", + "gas_remaining" + |), + Value.Integer 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + outcome + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "revm::inspector::Inspector" + (Self DB) + (* Trait polymorphic types *) [ (* DB *) DB ] + (* Instance *) + [ + ("initialize_interp", InstanceField.Method (initialize_interp DB)); + ("step", InstanceField.Method (step DB)); + ("step_end", InstanceField.Method (step_end DB)); + ("call_end", InstanceField.Method (call_end DB)); + ("create_end", InstanceField.Method (create_end DB)) + ]. + End Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_DB_for_revm_inspector_gas_GasInspector. + End gas. +End inspector. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/handler_register.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/handler_register.md new file mode 100644 index 00000000..b9f8189f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/handler_register.md @@ -0,0 +1,5242 @@ +# ๐Ÿ“ handler_register.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/inspector/handler_register.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module inspector. + Module handler_register. + (* Trait *) + (* Empty module 'GetInspector' *) + + Module Impl_revm_inspector_handler_register_GetInspector_where_revm_primitives_db_Database_DB_where_revm_inspector_Inspector_INSP_DB_DB_for_INSP. + Definition Self (DB INSP : Ty.t) : Ty.t := INSP. + + (* + fn get_inspector(&mut self) -> &mut impl Inspector { + self + } + *) + Definition get_inspector (DB INSP : Ty.t) (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + let Self : Ty.t := Self DB INSP in + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| self |))) + | _, _ => M.impossible + end. + + Axiom Implements : + forall (DB INSP : Ty.t), + M.IsTraitInstance + "revm::inspector::handler_register::GetInspector" + (Self DB INSP) + (* Trait polymorphic types *) [ (* DB *) DB ] + (* Instance *) [ ("get_inspector", InstanceField.Method (get_inspector DB INSP)) ]. + End Impl_revm_inspector_handler_register_GetInspector_where_revm_primitives_db_Database_DB_where_revm_inspector_Inspector_INSP_DB_DB_for_INSP. + + (* + pub fn inspector_handle_register<'a, DB: Database, EXT: GetInspector>( + handler: &mut EvmHandler<'a, EXT, DB>, + ) { + // Every instruction inside flat table that is going to be wrapped by inspector calls. + let table = handler + .take_instruction_table() + .expect("Handler must have instruction table"); + let mut table = match table { + InstructionTables::Plain(table) => table + .into_iter() + .map(|i| inspector_instruction(i)) + .collect::>(), + InstructionTables::Boxed(table) => table + .into_iter() + .map(|i| inspector_instruction(i)) + .collect::>(), + }; + + // Register inspector Log instruction. + let mut inspect_log = |index: u8| { + if let Some(i) = table.get_mut(index as usize) { + let old = core::mem::replace(i, Box::new(|_, _| ())); + *i = Box::new( + move |interpreter: &mut Interpreter, host: &mut Evm<'a, EXT, DB>| { + let old_log_len = host.context.evm.journaled_state.logs.len(); + old(interpreter, host); + // check if log was added. It is possible that revert happened + // cause of gas or stack underflow. + if host.context.evm.journaled_state.logs.len() == old_log_len + 1 { + // clone log. + // TODO decide if we should remove this and leave the comment + // that log can be found as journaled_state. + let last_log = host + .context + .evm + .journaled_state + .logs + .last() + .unwrap() + .clone(); + // call Inspector + host.context + .external + .get_inspector() + .log(&mut host.context.evm, &last_log); + } + }, + ) + } + }; + + inspect_log(opcode::LOG0); + inspect_log(opcode::LOG1); + inspect_log(opcode::LOG2); + inspect_log(opcode::LOG3); + inspect_log(opcode::LOG4); + + // // register selfdestruct function. + if let Some(i) = table.get_mut(opcode::SELFDESTRUCT as usize) { + let old = core::mem::replace(i, Box::new(|_, _| ())); + *i = Box::new( + move |interpreter: &mut Interpreter, host: &mut Evm<'a, EXT, DB>| { + // execute selfdestruct + old(interpreter, host); + // check if selfdestruct was successful and if journal entry is made. + if let Some(JournalEntry::AccountDestroyed { + address, + target, + had_balance, + .. + }) = host + .context + .evm + .journaled_state + .journal + .last() + .unwrap() + .last() + { + host.context.external.get_inspector().selfdestruct( + *address, + *target, + *had_balance, + ); + } + }, + ) + } + + // cast vector to array. + handler.set_instruction_table(InstructionTables::Boxed( + table.try_into().unwrap_or_else(|_| unreachable!()), + )); + + // call and create input stack shared between handlers. They are used to share + // inputs in *_end Inspector calls. + let call_input_stack = Rc::>>::new(RefCell::new(Vec::new())); + let create_input_stack = Rc::>>::new(RefCell::new(Vec::new())); + let eofcreate_input_stack = Rc::>>::new(RefCell::new(Vec::new())); + + // Create handler + let create_input_stack_inner = create_input_stack.clone(); + let old_handle = handler.execution.create.clone(); + handler.execution.create = Arc::new( + move |ctx, mut inputs| -> Result> { + let inspector = ctx.external.get_inspector(); + // call inspector create to change input or return outcome. + if let Some(outcome) = inspector.create(&mut ctx.evm, &mut inputs) { + create_input_stack_inner.borrow_mut().push(inputs.clone()); + return Ok(FrameOrResult::Result(FrameResult::Create(outcome))); + } + create_input_stack_inner.borrow_mut().push(inputs.clone()); + + let mut frame_or_result = old_handle(ctx, inputs); + if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { + ctx.external + .get_inspector() + .initialize_interp(frame.interpreter_mut(), &mut ctx.evm) + } + frame_or_result + }, + ); + + // Call handler + let call_input_stack_inner = call_input_stack.clone(); + let old_handle = handler.execution.call.clone(); + handler.execution.call = Arc::new( + move |ctx, mut inputs| -> Result> { + // Call inspector to change input or return outcome. + let outcome = ctx.external.get_inspector().call(&mut ctx.evm, &mut inputs); + call_input_stack_inner.borrow_mut().push(inputs.clone()); + if let Some(outcome) = outcome { + return Ok(FrameOrResult::Result(FrameResult::Call(outcome))); + } + + let mut frame_or_result = old_handle(ctx, inputs); + if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { + ctx.external + .get_inspector() + .initialize_interp(frame.interpreter_mut(), &mut ctx.evm) + } + frame_or_result + }, + ); + + // TODO(EOF) EOF create call. + + // call outcome + let call_input_stack_inner = call_input_stack.clone(); + let old_handle = handler.execution.insert_call_outcome.clone(); + handler.execution.insert_call_outcome = + Arc::new(move |ctx, frame, shared_memory, mut outcome| { + let call_inputs = call_input_stack_inner.borrow_mut().pop().unwrap(); + outcome = ctx + .external + .get_inspector() + .call_end(&mut ctx.evm, &call_inputs, outcome); + old_handle(ctx, frame, shared_memory, outcome) + }); + + // create outcome + let create_input_stack_inner = create_input_stack.clone(); + let old_handle = handler.execution.insert_create_outcome.clone(); + handler.execution.insert_create_outcome = Arc::new(move |ctx, frame, mut outcome| { + let create_inputs = create_input_stack_inner.borrow_mut().pop().unwrap(); + outcome = ctx + .external + .get_inspector() + .create_end(&mut ctx.evm, &create_inputs, outcome); + old_handle(ctx, frame, outcome) + }); + + // TODO(EOF) EOF create handle. + + // last frame outcome + let old_handle = handler.execution.last_frame_return.clone(); + handler.execution.last_frame_return = Arc::new(move |ctx, frame_result| { + let inspector = ctx.external.get_inspector(); + match frame_result { + FrameResult::Call(outcome) => { + let call_inputs = call_input_stack.borrow_mut().pop().unwrap(); + *outcome = inspector.call_end(&mut ctx.evm, &call_inputs, outcome.clone()); + } + FrameResult::Create(outcome) => { + let create_inputs = create_input_stack.borrow_mut().pop().unwrap(); + *outcome = inspector.create_end(&mut ctx.evm, &create_inputs, outcome.clone()); + } + FrameResult::EOFCreate(outcome) => { + let eofcreate_inputs = eofcreate_input_stack.borrow_mut().pop().unwrap(); + *outcome = + inspector.eofcreate_end(&mut ctx.evm, &eofcreate_inputs, outcome.clone()); + } + } + old_handle(ctx, frame_result) + }); + } + *) + Definition inspector_handle_register (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ DB; EXT ], [ handler ] => + ltac:(M.monadic + (let handler := M.alloc (| handler |) in + M.read (| + let~ table := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "revm_interpreter::opcode::InstructionTables") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "take_instruction_table", + [] + |), + [ M.read (| handler |) ] + |); + M.read (| Value.String "Handler must have instruction table" |) + ] + |) + |) in + let~ table := + M.copy (| + M.match_operator (| + table, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Plain", + 0 + |) in + let table := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "core::array::iter::IntoIter") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + ] + (Ty.tuple []) + ]; + Ty.function + [ + Ty.tuple + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + ] + (Ty.tuple []) + ] + ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::array::iter::IntoIter") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + ] + (Ty.tuple []) + ], + [], + "map", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] + ] + ] + (Ty.tuple []) + ] + ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "array") + [ + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + ] + (Ty.tuple []) + ], + [], + "into_iter", + [] + |), + [ M.read (| table |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let i := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm::inspector::handler_register::inspector_instruction", + [ + EXT; + DB; + Ty.function + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "revm::evm::Evm") + [ EXT; DB ] + ] + ] + (Ty.tuple []) + ] + |), + [ M.read (| i |) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm_interpreter::opcode::InstructionTables::Boxed", + 0 + |) in + let table := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::map::Map") + [ + Ty.apply + (Ty.path "core::array::iter::IntoIter") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ] + ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ], + [], + "collect", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::array::iter::IntoIter") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "map", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ] + ] + (Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "into_iter", + [] + |), + [ M.read (| table |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let i := M.copy (| ฮณ |) in + M.call_closure (| + M.get_function (| + "revm::inspector::handler_register::inspector_instruction", + [ + EXT; + DB; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ M.read (| i |) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + |) + |))) + ] + |) + |) in + let~ inspect_log := + M.alloc (| + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let index := M.copy (| ฮณ |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "get_mut", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ table ] + |); + M.rust_cast (M.read (| index |)) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let i := M.copy (| ฮณ0_0 |) in + let~ old := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::replace", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.read (| i |); + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "revm::evm::Evm") + [ EXT; DB ] + ] + ] + ] + (Ty.tuple []); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (Value.Tuple [])) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)) + ] + |) + |) in + M.write (| + M.read (| i |), + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "revm::evm::Evm") + [ EXT; DB ] + ] + ] + ] + (Ty.tuple []); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let interpreter := + M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let host := + M.copy (| ฮณ |) in + M.read (| + let~ old_log_len := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloy_primitives::log::Log") + [ + Ty.path + "alloy_primitives::log::LogData" + ]; + Ty.path + "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ DB + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + host + |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |), + "revm::journaled_state::JournaledState", + "logs" + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path + "alloc::alloc::Global" + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path + "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path + "&mut") + [ + Ty.apply + (Ty.path + "revm::evm::Evm") + [ + EXT; + DB + ] + ] + ] + ], + "call", + [] + |), + [ + old; + Value.Tuple + [ + M.read (| + interpreter + |); + M.read (| + host + |) + ] + ] + |) + |) in + M.match_operator (| + M.alloc (| + Value.Tuple [] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloy_primitives::log::Log") + [ + Ty.path + "alloy_primitives::log::LogData" + ]; + Ty.path + "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ + DB + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + host + |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |), + "revm::journaled_state::JournaledState", + "logs" + |) + ] + |)) + (BinOp.Wrap.add + Integer.Usize + (M.read (| + old_log_len + |)) + (Value.Integer + 1)) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| + ฮณ + |), + Value.Bool + true + |) in + let~ last_log := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path + "alloy_primitives::log::Log") + [ + Ty.path + "alloy_primitives::log::LogData" + ], + [], + "clone", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.apply + (Ty.path + "&") + [ + Ty.apply + (Ty.path + "alloy_primitives::log::Log") + [ + Ty.path + "alloy_primitives::log::LogData" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "slice") + [ + Ty.apply + (Ty.path + "alloy_primitives::log::Log") + [ + Ty.path + "alloy_primitives::log::LogData" + ] + ], + "last", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloy_primitives::log::Log") + [ + Ty.path + "alloy_primitives::log::LogData" + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ + DB + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + host + |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |), + "revm::journaled_state::JournaledState", + "logs" + |) + ] + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "log", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + EXT, + [ DB + ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + host + |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "external" + |) + ] + |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + host + |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |); + last_log + ] + |) + |) in + M.alloc (| + Value.Tuple [] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.Tuple [] + |))) + ] + |) + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnMut", + Ty.function [ Ty.tuple [ Ty.path "u8" ] ] (Ty.tuple []), + [ Ty.tuple [ Ty.path "u8" ] ], + "call_mut", + [] + |), + [ + inspect_log; + Value.Tuple + [ M.read (| M.get_constant (| "revm_interpreter::opcode::LOG0" |) |) ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnMut", + Ty.function [ Ty.tuple [ Ty.path "u8" ] ] (Ty.tuple []), + [ Ty.tuple [ Ty.path "u8" ] ], + "call_mut", + [] + |), + [ + inspect_log; + Value.Tuple + [ M.read (| M.get_constant (| "revm_interpreter::opcode::LOG1" |) |) ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnMut", + Ty.function [ Ty.tuple [ Ty.path "u8" ] ] (Ty.tuple []), + [ Ty.tuple [ Ty.path "u8" ] ], + "call_mut", + [] + |), + [ + inspect_log; + Value.Tuple + [ M.read (| M.get_constant (| "revm_interpreter::opcode::LOG2" |) |) ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnMut", + Ty.function [ Ty.tuple [ Ty.path "u8" ] ] (Ty.tuple []), + [ Ty.tuple [ Ty.path "u8" ] ], + "call_mut", + [] + |), + [ + inspect_log; + Value.Tuple + [ M.read (| M.get_constant (| "revm_interpreter::opcode::LOG3" |) |) ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::FnMut", + Ty.function [ Ty.tuple [ Ty.path "u8" ] ] (Ty.tuple []), + [ Ty.tuple [ Ty.path "u8" ] ], + "call_mut", + [] + |), + [ + inspect_log; + Value.Tuple + [ M.read (| M.get_constant (| "revm_interpreter::opcode::LOG4" |) |) ] + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "get_mut", + [ Ty.path "usize" ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ table ] + |); + M.rust_cast + (M.read (| + M.get_constant (| "revm_interpreter::opcode::SELFDESTRUCT" |) + |)) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let i := M.copy (| ฮณ0_0 |) in + let~ old := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::replace", + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ + M.read (| i |); + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] + ] + ] + ] + (Ty.tuple []); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| ฮฑ1 |), + [ fun ฮณ => ltac:(M.monadic (Value.Tuple [])) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)) + ] + |) + |) in + M.write (| + M.read (| i |), + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ] ] + ] + ] + (Ty.tuple []); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let interpreter := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let host := M.copy (| ฮณ |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "revm::evm::Evm") + [ EXT; DB ] + ] + ] + ], + "call", + [] + |), + [ + old; + Value.Tuple + [ + M.read (| interpreter |); + M.read (| host |) + ] + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.path + "revm::journaled_state::JournalEntry" + ], + "last", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm::journaled_state::JournalEntry"; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.apply + (Ty.path "&") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm::journaled_state::JournalEntry"; + Ty.path + "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "slice") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm::journaled_state::JournalEntry"; + Ty.path + "alloc::alloc::Global" + ] + ], + "last", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm::journaled_state::JournalEntry"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "revm::context::evm_context::EvmContext") + [ + DB + ], + [], + "deref", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| + host + |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |), + "revm::context::inner_evm_context::InnerEvmContext", + "journaled_state" + |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |) + ] + |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "address" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "target" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "had_balance" + |) in + let address := M.alloc (| ฮณ2_0 |) in + let target := M.alloc (| ฮณ2_1 |) in + let had_balance := + M.alloc (| ฮณ2_2 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "selfdestruct", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + EXT, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| host |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "external" + |) + ] + |); + M.read (| + M.read (| address |) + |); + M.read (| + M.read (| target |) + |); + M.read (| + M.read (| had_balance |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "revm::handler::Handler") + [ Ty.apply (Ty.path "revm::evm::Evm") [ EXT; DB ]; EXT; DB ], + "set_instruction_table", + [] + |), + [ + M.read (| handler |); + Value.StructTuple + "revm_interpreter::opcode::InstructionTables::Boxed" + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "unwrap_or_else", + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ] + ] + (Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::convert::TryInto", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "try_into", + [] + |), + [ M.read (| table |) ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (M.never_to_any (| + M.call_closure (| + M.get_function (| "core::panicking::panic", [] |), + [ + M.read (| + Value.String + "internal error: entered unreachable code" + |) + ] + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + ] + ] + |) + |) in + let~ call_input_stack := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::rc::Rc") + [ + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + ] + |) + ] + |) + |) in + let~ create_input_stack := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::rc::Rc") + [ + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + ] + |) + ] + |) + |) in + let~ eofcreate_input_stack := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::rc::Rc") + [ + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ] + ], + "new", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + ] + |) + ] + |) + |) in + let~ create_input_stack_inner := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::rc::Rc") + [ + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ create_input_stack ] + |) + |) in + let~ old_handle := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "create" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "create" + |), + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ] + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ctx := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let inputs := M.copy (| ฮณ |) in + M.read (| + let~ inspector := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + EXT, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "external" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "create", + [] + |), + [ + M.read (| inspector |); + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |); + M.read (| inputs |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let outcome := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "core::cell::RefMut") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + [], + "deref_mut", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + "borrow_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::rc::Rc") + [ + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + create_input_stack_inner + ] + |) + ] + |) + |) + ] + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ inputs ] + |) + ] + |) + |) in + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructTuple + "revm::frame::FrameOrResult::Result" + [ + Value.StructTuple + "revm::frame::FrameResult::Create" + [ M.read (| outcome |) ] + ] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "core::cell::RefMut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "deref_mut", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + "borrow_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::rc::Rc") + [ + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ create_input_stack_inner ] + |) + ] + |) + |) + ] + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ inputs ] + |) + ] + |) + |) in + let~ frame_or_result := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "revm::context::Context") + [ EXT; DB ] + ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ old_handle ] + |); + Value.Tuple + [ M.read (| ctx |); M.read (| inputs |) ] + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.alloc (| frame_or_result |) in + let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ1_0, + "revm::frame::FrameOrResult::Frame", + 0 + |) in + let frame := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "initialize_interp", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + EXT, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "external" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::Frame", + "interpreter_mut", + [] + |), + [ M.read (| frame |) ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + frame_or_result + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)) + |) in + let~ call_input_stack_inner := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::rc::Rc") + [ + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ call_input_stack ] + |) + |) in + let~ old_handle := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "call" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "call" + |), + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ] + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm::frame::FrameOrResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ctx := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let inputs := M.copy (| ฮณ |) in + M.read (| + let~ outcome := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + EXT, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "external" + |) + ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |); + M.read (| inputs |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "core::cell::RefMut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "deref_mut", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + "borrow_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::rc::Rc") + [ + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ call_input_stack_inner ] + |) + ] + |) + |) + ] + |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ inputs ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := outcome in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let outcome := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructTuple + "revm::frame::FrameOrResult::Result" + [ + Value.StructTuple + "revm::frame::FrameResult::Call" + [ M.read (| outcome |) ] + ] + ] + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ frame_or_result := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "revm::context::Context") + [ EXT; DB ] + ]; + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ old_handle ] + |); + Value.Tuple + [ M.read (| ctx |); M.read (| inputs |) ] + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.alloc (| frame_or_result |) in + let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::result::Result::Ok", + 0 + |) in + let ฮณ2_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ1_0, + "revm::frame::FrameOrResult::Frame", + 0 + |) in + let frame := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "initialize_interp", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + EXT, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "external" + |) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::frame::Frame", + "interpreter_mut", + [] + |), + [ M.read (| frame |) ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |) in + frame_or_result + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)) + |) in + let~ call_input_stack_inner := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::rc::Rc") + [ + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ call_input_stack ] + |) + |) in + let~ old_handle := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "insert_call_outcome" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "insert_call_outcome" + |), + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::Frame" ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory" + ]; + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1; ฮฑ2; ฮฑ3 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ctx := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let frame := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ2 |), + [ + fun ฮณ => + ltac:(M.monadic + (let shared_memory := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ3 |), + [ + fun ฮณ => + ltac:(M.monadic + (let outcome := M.copy (| ฮณ |) in + M.read (| + let~ call_inputs := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::option::Option") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ], + "pop", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "core::cell::RefMut") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + [], + "deref_mut", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + "borrow_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::rc::Rc") + [ + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + call_input_stack_inner + ] + |) + ] + |) + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + outcome, + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "call_end", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + EXT, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "external" + |) + ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |); + M.read (| call_inputs |); + M.read (| outcome |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "revm::context::Context") + [ EXT; DB ] + ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm::frame::Frame" + ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::shared_memory::SharedMemory" + ]; + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome" + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ old_handle ] + |); + Value.Tuple + [ + M.read (| ctx |); + M.read (| frame |); + M.read (| + shared_memory + |); + M.read (| outcome |) + ] + ] + |) + |) + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)) + |) in + let~ create_input_stack_inner := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::rc::Rc") + [ + Ty.apply + (Ty.path "core::cell::RefCell") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ create_input_stack ] + |) + |) in + let~ old_handle := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "insert_create_outcome" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "insert_create_outcome" + |), + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::Frame" ]; + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome" + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1; ฮฑ2 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ctx := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let frame := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ2 |), + [ + fun ฮณ => + ltac:(M.monadic + (let outcome := M.copy (| ฮณ |) in + M.read (| + let~ create_inputs := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ], + "pop", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "core::cell::RefMut") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + [], + "deref_mut", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + "borrow_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::rc::Rc") + [ + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + create_input_stack_inner + ] + |) + ] + |) + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + outcome, + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "create_end", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + EXT, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "external" + |) + ] + |); + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |); + M.read (| create_inputs |); + M.read (| outcome |) + ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path + "revm::context::Context") + [ EXT; DB ] + ]; + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm::frame::Frame" + ]; + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome" + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ old_handle ] + |); + Value.Tuple + [ + M.read (| ctx |); + M.read (| frame |); + M.read (| outcome |) + ] + ] + |) + |) + |))) + ] + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)) + |) in + let~ old_handle := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", []); + ("existential predicate with variables", []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "last_frame_return" + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| handler |), + "revm::handler::Handler", + "execution" + |), + "revm::handler::handle_types::execution::ExecutionHandler", + "last_frame_return" + |), + (* Unsize *) + M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::context::Context") [ EXT; DB ] ]; + Ty.apply (Ty.path "&mut") [ Ty.path "revm::frame::FrameResult" ] + ] + ] + (Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple []; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ]); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ctx := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let frame_result := M.copy (| ฮณ |) in + M.read (| + let~ inspector := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + EXT, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "external" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + frame_result, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Call", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + let~ call_inputs := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ], + "pop", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "core::cell::RefMut") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + [], + "deref_mut", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + "borrow_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::rc::Rc") + [ + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::call_inputs::CallInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ call_input_stack + ] + |) + ] + |) + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| outcome |), + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "call_end", + [] + |), + [ + M.read (| inspector |); + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |); + M.read (| call_inputs |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm_interpreter::interpreter_action::call_outcome::CallOutcome", + [], + "clone", + [] + |), + [ M.read (| outcome |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::Create", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + let~ create_inputs := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ], + "pop", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "core::cell::RefMut") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + [], + "deref_mut", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ], + "borrow_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::rc::Rc") + [ + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.apply + (Ty.path + "alloc::boxed::Box") + [ + Ty.path + "revm_interpreter::interpreter_action::create_inputs::CreateInputs"; + Ty.path + "alloc::alloc::Global" + ]; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + create_input_stack + ] + |) + ] + |) + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| outcome |), + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "create_end", + [] + |), + [ + M.read (| inspector |); + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |); + M.read (| create_inputs |); + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm_interpreter::interpreter_action::create_outcome::CreateOutcome", + [], + "clone", + [] + |), + [ M.read (| outcome |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "revm::frame::FrameResult::EOFCreate", + 0 + |) in + let outcome := M.alloc (| ฮณ1_0 |) in + let~ eofcreate_inputs := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput" + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path + "alloc::alloc::Global" + ], + "pop", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path + "core::cell::RefMut") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path + "alloc::alloc::Global" + ] + ], + [], + "deref_mut", + [] + |), + [ + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path + "alloc::alloc::Global" + ] + ], + "borrow_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path + "alloc::rc::Rc") + [ + Ty.apply + (Ty.path + "core::cell::RefCell") + [ + Ty.apply + (Ty.path + "alloc::vec::Vec") + [ + Ty.path + "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput"; + Ty.path + "alloc::alloc::Global" + ] + ]; + Ty.path + "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ + eofcreate_input_stack + ] + |) + ] + |) + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.read (| outcome |), + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "eofcreate_end", + [] + |), + [ + M.read (| inspector |); + M.SubPointer.get_struct_record_field (| + M.read (| ctx |), + "revm::context::Context", + "evm" + |); + eofcreate_inputs; + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path + "revm_interpreter::interpreter_action::eof_create_outcome::EOFCreateOutcome", + [], + "clone", + [] + |), + [ M.read (| outcome |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ], + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "revm::context::Context") + [ EXT; DB ] + ]; + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm::frame::FrameResult" ] + ] + ], + "call", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::Deref", + Ty.apply + (Ty.path "alloc::sync::Arc") + [ + Ty.dyn + [ + ("existential predicate with variables", + []); + ("existential predicate with variables", + []) + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref", + [] + |), + [ old_handle ] + |); + Value.Tuple + [ + M.read (| ctx |); + M.read (| frame_result |) + ] + ] + |) + |) + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |)) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom Function_inspector_handle_register : + M.IsFunction + "revm::inspector::handler_register::inspector_handle_register" + inspector_handle_register. + + (* + pub fn inspector_instruction< + 'a, + INSP: GetInspector, + DB: Database, + Instruction: Fn(&mut Interpreter, &mut Evm<'a, INSP, DB>) + 'a, + >( + instruction: Instruction, + ) -> BoxedInstruction<'a, Evm<'a, INSP, DB>> { + Box::new( + move |interpreter: &mut Interpreter, host: &mut Evm<'a, INSP, DB>| { + // SAFETY: as the PC was already incremented we need to subtract 1 to preserve the + // old Inspector behavior. + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.sub(1) }; + + host.context + .external + .get_inspector() + .step(interpreter, &mut host.context.evm); + if interpreter.instruction_result != InstructionResult::Continue { + return; + } + + // return PC to old value + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.add(1) }; + + // execute instruction. + instruction(interpreter, host); + + host.context + .external + .get_inspector() + .step_end(interpreter, &mut host.context.evm); + }, + ) + } + *) + Definition inspector_instruction (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ INSP; DB; Instruction ], [ instruction ] => + ltac:(M.monadic + (let instruction := M.alloc (| instruction |) in + (* Unsize *) + M.pointer_coercion + (* Unsize *) + (M.pointer_coercion + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_interpreter::interpreter::Interpreter" ]; + Ty.apply + (Ty.path "&mut") + [ Ty.apply (Ty.path "revm::evm::Evm") [ INSP; DB ] ] + ] + ] + (Ty.tuple []); + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0; ฮฑ1 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let interpreter := M.copy (| ฮณ |) in + M.match_operator (| + M.alloc (| ฮฑ1 |), + [ + fun ฮณ => + ltac:(M.monadic + (let host := M.copy (| ฮณ |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "sub", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + Value.Integer 1 + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "step", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + INSP, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| host |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "external" + |) + ] + |); + M.read (| interpreter |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| host |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "revm_interpreter::instruction_result::InstructionResult", + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ], + "ne", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_result" + |); + M.alloc (| + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::Continue" + [] + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| Value.Tuple [] |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |), + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "*const") [ Ty.path "u8" ], + "add", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| interpreter |), + "revm_interpreter::interpreter::Interpreter", + "instruction_pointer" + |) + |); + Value.Integer 1 + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::function::Fn", + Instruction, + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_interpreter::interpreter::Interpreter" + ]; + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "revm::evm::Evm") + [ INSP; DB ] + ] + ] + ], + "call", + [] + |), + [ + instruction; + Value.Tuple + [ M.read (| interpreter |); M.read (| host |) + ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "revm::inspector::Inspector", + Ty.associated, + [ DB ], + "step_end", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm::inspector::handler_register::GetInspector", + INSP, + [ DB ], + "get_inspector", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| host |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "external" + |) + ] + |); + M.read (| interpreter |); + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| host |), + "revm::evm::Evm", + "context" + |), + "revm::context::Context", + "evm" + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |))))) + | _, _ => M.impossible + end. + + Axiom Function_inspector_instruction : + M.IsFunction "revm::inspector::handler_register::inspector_instruction" inspector_instruction. + End handler_register. +End inspector. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/noop.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/noop.md new file mode 100644 index 00000000..9d515167 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/inspector/noop.md @@ -0,0 +1,240 @@ +# ๐Ÿ“ noop.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/inspector/noop.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module inspector. + Module noop. + (* StructTuple + { + name := "NoOpInspector"; + ty_params := []; + fields := []; + } *) + + Module Impl_core_clone_Clone_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| M.read (| self |) |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_marker_Copy_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_fmt_Debug_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| Ty.path "core::fmt::Formatter", "write_str", [] |), + [ M.read (| f |); M.read (| Value.String "NoOpInspector" |) ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_default_Default_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + (* Default *) + Definition default (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [] => ltac:(M.monadic (Value.StructTuple "revm::inspector::noop::NoOpInspector" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::default::Default" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("default", InstanceField.Method default) ]. + End Impl_core_default_Default_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_marker_StructuralPartialEq_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_cmp_PartialEq_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.Bool true)) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_marker_StructuralEq_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_cmp_Eq_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_cmp_PartialOrd_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + (* PartialOrd *) + Definition partial_cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple + "core::option::Option::Some" + [ Value.StructTuple "core::cmp::Ordering::Equal" [] ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialOrd" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("partial_cmp", InstanceField.Method partial_cmp) ]. + End Impl_core_cmp_PartialOrd_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_cmp_Ord_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + (* Ord *) + Definition cmp (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + Value.StructTuple "core::cmp::Ordering::Equal" [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Ord" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("cmp", InstanceField.Method cmp) ]. + End Impl_core_cmp_Ord_for_revm_inspector_noop_NoOpInspector. + + Module Impl_core_hash_Hash_for_revm_inspector_noop_NoOpInspector. + Definition Self : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + Value.Tuple [])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_inspector_noop_NoOpInspector. + + Module Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_DB_for_revm_inspector_noop_NoOpInspector. + Definition Self (DB : Ty.t) : Ty.t := Ty.path "revm::inspector::noop::NoOpInspector". + + Axiom Implements : + forall (DB : Ty.t), + M.IsTraitInstance + "revm::inspector::Inspector" + (Self DB) + (* Trait polymorphic types *) [ (* DB *) DB ] + (* Instance *) []. + End Impl_revm_inspector_Inspector_where_revm_primitives_db_Database_DB_DB_for_revm_inspector_noop_NoOpInspector. + End noop. +End inspector. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/journaled_state.md b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/journaled_state.md new file mode 100644 index 00000000..98caafb1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-coq/translations/revm/journaled_state.md @@ -0,0 +1,10924 @@ +# ๐Ÿ“ journaled_state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-rust/tree/main/CoqOfRust/revm/translations/revm/journaled_state.v) + +```coq +(* Generated by coq-of-rust *) +Require Import CoqOfRust.CoqOfRust. + +Module journaled_state. + (* StructRecord + { + name := "JournaledState"; + ty_params := []; + fields := + [ + ("state", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ]); + ("transient_storage", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ Ty.path "alloy_primitives::bits::address::Address"; Ty.path "ruint::Uint" ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ]); + ("logs", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ]); + ("depth", Ty.path "usize"); + ("journal", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ Ty.path "revm::journaled_state::JournalEntry"; Ty.path "alloc::alloc::Global" ]; + Ty.path "alloc::alloc::Global" + ]); + ("spec", Ty.path "revm_primitives::specification::SpecId"); + ("warm_preloaded_addresses", + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ]) + ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_journaled_state_JournaledState. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournaledState". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + let~ names := + M.alloc (| + M.alloc (| + Value.Array + [ + M.read (| Value.String "state" |); + M.read (| Value.String "transient_storage" |); + M.read (| Value.String "logs" |); + M.read (| Value.String "depth" |); + M.read (| Value.String "journal" |); + M.read (| Value.String "spec" |); + M.read (| Value.String "warm_preloaded_addresses" |) + ] + |) + |) in + let~ values := + M.alloc (| + (* Unsize *) + M.pointer_coercion + (M.alloc (| + Value.Array + [ + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "transient_storage" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "logs" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "depth" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |)); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "spec" + |)); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "warm_preloaded_addresses" + |) + |)) + ] + |)) + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_fields_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "JournaledState" |); + (* Unsize *) M.pointer_coercion (M.read (| names |)); + M.read (| values |) + ] + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_journaled_state_JournaledState. + + Module Impl_core_clone_Clone_for_revm_journaled_state_JournaledState. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournaledState". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + Value.StructRecord + "revm::journaled_state::JournaledState" + [ + ("state", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |) + ] + |)); + ("transient_storage", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "transient_storage" + |) + ] + |)); + ("logs", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "logs" + |) + ] + |)); + ("depth", + M.call_closure (| + M.get_trait_method (| "core::clone::Clone", Ty.path "usize", [], "clone", [] |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "depth" + |) + ] + |)); + ("journal", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |)); + ("spec", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::specification::SpecId", + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "spec" + |) + ] + |)); + ("warm_preloaded_addresses", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + [], + "clone", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "warm_preloaded_addresses" + |) + ] + |)) + ])) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_journaled_state_JournaledState. + + Module Impl_core_marker_StructuralPartialEq_for_revm_journaled_state_JournaledState. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournaledState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_journaled_state_JournaledState. + + Module Impl_core_cmp_PartialEq_for_revm_journaled_state_JournaledState. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournaledState". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::journaled_state::JournaledState", + "state" + |) + ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "transient_storage" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::journaled_state::JournaledState", + "transient_storage" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "logs" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::journaled_state::JournaledState", + "logs" + |) + ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "depth" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::journaled_state::JournaledState", + "depth" + |) + |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "revm_primitives::specification::SpecId", + [ Ty.path "revm_primitives::specification::SpecId" ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "spec" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::journaled_state::JournaledState", + "spec" + |) + ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + [ + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ] + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "warm_preloaded_addresses" + |); + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::journaled_state::JournaledState", + "warm_preloaded_addresses" + |) + ] + |))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_journaled_state_JournaledState. + + Module Impl_core_marker_StructuralEq_for_revm_journaled_state_JournaledState. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournaledState". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_journaled_state_JournaledState. + + Module Impl_core_cmp_Eq_for_revm_journaled_state_JournaledState. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournaledState". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_journaled_state_JournaledState. + + Module Impl_revm_journaled_state_JournaledState. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournaledState". + + (* + pub fn new(spec: SpecId, warm_preloaded_addresses: HashSet
) -> JournaledState { + Self { + state: HashMap::new(), + transient_storage: TransientStorage::default(), + logs: Vec::new(), + journal: vec![vec![]], + depth: 0, + spec, + warm_preloaded_addresses, + } + } + *) + Definition new (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ spec; warm_preloaded_addresses ] => + ltac:(M.monadic + (let spec := M.alloc (| spec |) in + let warm_preloaded_addresses := M.alloc (| warm_preloaded_addresses |) in + Value.StructRecord + "revm::journaled_state::JournaledState" + [ + ("state", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |)); + ("transient_storage", + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |)); + ("logs", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |)); + ("journal", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "into_vec", + [ Ty.path "alloc::alloc::Global" ] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + ] + |) + ] + |) + |)) + ] + |)); + ("depth", Value.Integer 0); + ("spec", M.read (| spec |)); + ("warm_preloaded_addresses", M.read (| warm_preloaded_addresses |)) + ])) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_new : M.IsAssociatedFunction Self "new" new. + + (* + pub fn state(&mut self) -> &mut State { + &mut self.state + } + *) + Definition state (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_state : M.IsAssociatedFunction Self "state" state. + + (* + pub fn set_spec_id(&mut self, spec: SpecId) { + self.spec = spec; + } + *) + Definition set_spec_id (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; spec ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let spec := M.alloc (| spec |) in + M.read (| + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "spec" + |), + M.read (| spec |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_spec_id : M.IsAssociatedFunction Self "set_spec_id" set_spec_id. + + (* + pub fn touch(&mut self, address: &Address) { + if let Some(account) = self.state.get_mut(address) { + Self::touch_account(self.journal.last_mut().unwrap(), address, account); + } + } + *) + Definition touch (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + M.read (| address |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let account := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "touch_account", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + M.read (| address |); + M.read (| account |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_touch : M.IsAssociatedFunction Self "touch" touch. + + (* + fn touch_account(journal: &mut Vec, address: &Address, account: &mut Account) { + if !account.is_touched() { + journal.push(JournalEntry::AccountTouched { address: *address }); + account.mark_touch(); + } + } + *) + Definition touch_account (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ journal; address; account ] => + ltac:(M.monadic + (let journal := M.alloc (| journal |) in + let address := M.alloc (| address |) in + let account := M.alloc (| account |) in + M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_touched", + [] + |), + [ M.read (| account |) ] + |)) + |)) in + let _ := M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.read (| journal |); + Value.StructRecord + "revm::journaled_state::JournalEntry::AccountTouched" + [ ("address", M.read (| M.read (| address |) |)) ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "mark_touch", + [] + |), + [ M.read (| account |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_touch_account : + M.IsAssociatedFunction Self "touch_account" touch_account. + + (* + pub fn clear(&mut self) { + let spec = self.spec; + *self = Self::new(spec, HashSet::new()); + } + *) + Definition clear (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ spec := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "spec" + |) + |) in + let~ _ := + M.write (| + M.read (| self |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "new", + [] + |), + [ + M.read (| spec |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "new", + [] + |), + [] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_clear : M.IsAssociatedFunction Self "clear" clear. + + (* + pub fn finalize(&mut self) -> (State, Vec) { + let Self { + state, + transient_storage, + logs, + depth, + journal, + // kept, see [Self::new] + spec: _, + warm_preloaded_addresses: _, + } = self; + + *transient_storage = TransientStorage::default(); + *journal = vec![vec![]]; + *depth = 0; + let state = mem::take(state); + let logs = mem::take(logs); + + (state, logs) + } + *) + Definition finalize (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournaledState", + "state" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournaledState", + "transient_storage" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournaledState", + "logs" + |) in + let ฮณ1_3 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournaledState", + "depth" + |) in + let ฮณ1_4 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournaledState", + "journal" + |) in + let ฮณ1_5 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournaledState", + "spec" + |) in + let ฮณ1_6 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournaledState", + "warm_preloaded_addresses" + |) in + let state := M.alloc (| ฮณ1_0 |) in + let transient_storage := M.alloc (| ฮณ1_1 |) in + let logs := M.alloc (| ฮณ1_2 |) in + let depth := M.alloc (| ฮณ1_3 |) in + let journal := M.alloc (| ฮณ1_4 |) in + let~ _ := + M.write (| + M.read (| transient_storage |), + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + [], + "default", + [] + |), + [] + |) + |) in + let~ _ := + M.write (| + M.read (| journal |), + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "into_vec", + [ Ty.path "alloc::alloc::Global" ] + |), + [ + (* Unsize *) + M.pointer_coercion + (M.read (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::boxed::Box") + [ + Ty.apply + (Ty.path "array") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ]; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [ + M.alloc (| + Value.Array + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "new", + [] + |), + [] + |) + ] + |) + ] + |) + |)) + ] + |) + |) in + let~ _ := M.write (| M.read (| depth |), Value.Integer 0 |) in + let~ state := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::take", + [ + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ] + ] + |), + [ M.read (| state |) ] + |) + |) in + let~ logs := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::mem::take", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ M.read (| logs |) ] + |) + |) in + M.alloc (| Value.Tuple [ M.read (| state |); M.read (| logs |) ] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_finalize : M.IsAssociatedFunction Self "finalize" finalize. + + (* + pub fn account(&self, address: Address) -> &Account { + self.state + .get(&address) + .expect("Account expected to be loaded") // Always assume that acc is already loaded + } + *) + Definition account (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "revm_primitives::state::Account" ] ], + "expect", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + address + ] + |); + M.read (| Value.String "Account expected to be loaded" |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_account : M.IsAssociatedFunction Self "account" account. + + (* + pub fn depth(&self) -> u64 { + self.depth as u64 + } + *) + Definition depth (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.rust_cast + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "depth" + |) + |)))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_depth : M.IsAssociatedFunction Self "depth" depth. + + (* + pub fn set_code(&mut self, address: Address, code: Bytecode) { + let account = self.state.get_mut(&address).unwrap(); + Self::touch_account(self.journal.last_mut().unwrap(), &address, account); + + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::CodeChange { address }); + + account.info.code_hash = code.hash_slow(); + account.info.code = Some(code); + } + *) + Definition set_code (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; code ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let code := M.alloc (| code |) in + M.read (| + let~ account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::state::Account" ] ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + address + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "touch_account", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + address; + M.read (| account |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + Value.StructRecord + "revm::journaled_state::JournalEntry::CodeChange" + [ ("address", M.read (| address |)) ] + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code_hash" + |), + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::bytecode::Bytecode", + "hash_slow", + [] + |), + [ code ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code" + |), + Value.StructTuple "core::option::Option::Some" [ M.read (| code |) ] + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_set_code : M.IsAssociatedFunction Self "set_code" set_code. + + (* + pub fn inc_nonce(&mut self, address: Address) -> Option { + let account = self.state.get_mut(&address).unwrap(); + // Check if nonce is going to overflow. + if account.info.nonce == u64::MAX { + return None; + } + Self::touch_account(self.journal.last_mut().unwrap(), &address, account); + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::NonceChange { address }); + + account.info.nonce += 1; + + Some(account.info.nonce) + } + *) + Definition inc_nonce (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + address + ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + |)) + (M.read (| M.get_constant (| "core::num::MAX" |) |)) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| Value.StructTuple "core::option::Option::None" [] |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "touch_account", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + address; + M.read (| account |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + Value.StructRecord + "revm::journaled_state::JournalEntry::NonceChange" + [ ("address", M.read (| address |)) ] + ] + |) + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |) in + M.write (| ฮฒ, BinOp.Wrap.add Integer.U64 (M.read (| ฮฒ |)) (Value.Integer 1) |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + |) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_inc_nonce : M.IsAssociatedFunction Self "inc_nonce" inc_nonce. + + (* + pub fn transfer( + &mut self, + from: &Address, + to: &Address, + balance: U256, + db: &mut DB, + ) -> Result, EVMError> { + // load accounts + self.load_account( *from, db)?; + self.load_account( *to, db)?; + + // sub balance from + let from_account = &mut self.state.get_mut(from).unwrap(); + Self::touch_account(self.journal.last_mut().unwrap(), from, from_account); + let from_balance = &mut from_account.info.balance; + + let Some(from_balance_incr) = from_balance.checked_sub(balance) else { + return Ok(Some(InstructionResult::OutOfFunds)); + }; + *from_balance = from_balance_incr; + + // add balance to + let to_account = &mut self.state.get_mut(to).unwrap(); + Self::touch_account(self.journal.last_mut().unwrap(), to, to_account); + let to_balance = &mut to_account.info.balance; + let Some(to_balance_decr) = to_balance.checked_add(balance) else { + return Ok(Some(InstructionResult::OverflowPayment)); + }; + *to_balance = to_balance_decr; + // Overflow of U256 balance is not possible to happen on mainnet. We don't bother to return funds from from_acc. + + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::BalanceTransfer { + from: *from, + to: *to, + balance, + }); + + Ok(None) + } + *) + Definition transfer (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ DB ], [ self; from; to; balance; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let from := M.alloc (| from |) in + let to := M.alloc (| to |) in + let balance := M.alloc (| balance |) in + let db := M.alloc (| db |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ M.read (| self |); M.read (| M.read (| from |) |); M.read (| db |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ M.read (| self |); M.read (| M.read (| to |) |); M.read (| db |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_interpreter::instruction_result::InstructionResult" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let~ from_account := + M.alloc (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + M.read (| from |) + ] + |) + ] + |) + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "touch_account", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + M.read (| from |); + M.read (| M.read (| from_account |) |) + ] + |) + |) in + let~ from_balance := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| from_account |) |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "checked_sub", [] |), + [ M.read (| M.read (| from_balance |) |); M.read (| balance |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let from_balance_incr := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| M.read (| from_balance |), M.read (| from_balance_incr |) |) in + let~ to_account := + M.alloc (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + M.read (| to |) + ] + |) + ] + |) + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "touch_account", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + M.read (| to |); + M.read (| M.read (| to_account |) |) + ] + |) + |) in + let~ to_balance := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| to_account |) |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "ruint::Uint", + "checked_add", + [] + |), + [ M.read (| M.read (| to_balance |) |); M.read (| balance |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let to_balance_decr := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.read (| to_balance |), + M.read (| to_balance_decr |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + Value.StructRecord + "revm::journaled_state::JournalEntry::BalanceTransfer" + [ + ("from", M.read (| M.read (| from |) |)); + ("to", M.read (| M.read (| to |) |)); + ("balance", M.read (| balance |)) + ] + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ Value.StructTuple "core::option::Option::None" [] ] + |))) + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_transfer : M.IsAssociatedFunction Self "transfer" transfer. + + (* + pub fn create_account_checkpoint( + &mut self, + caller: Address, + address: Address, + balance: U256, + spec_id: SpecId, + ) -> Result { + // Enter subroutine + let checkpoint = self.checkpoint(); + + // Newly created account is present, as we just loaded it. + let account = self.state.get_mut(&address).unwrap(); + let last_journal = self.journal.last_mut().unwrap(); + + // New account can be created if: + // Bytecode is not empty. + // Nonce is not zero + // Account is not precompile. + if account.info.code_hash != KECCAK_EMPTY + || account.info.nonce != 0 + || self.warm_preloaded_addresses.contains(&address) + { + self.checkpoint_revert(checkpoint); + return Err(InstructionResult::CreateCollision); + } + + // set account status to created. + account.mark_created(); + + // this entry will revert set nonce. + last_journal.push(JournalEntry::AccountCreated { address }); + account.info.code = None; + + // Set all storages to default value. They need to be present to act as accessed slots in access list. + // it shouldn't be possible for them to have different values then zero as code is not existing for this account, + // but because tests can change that assumption we are doing it. + let empty = StorageSlot::default(); + account + .storage + .iter_mut() + .for_each(|(_, slot)| *slot = empty.clone()); + + // touch account. This is important as for pre SpuriousDragon account could be + // saved even empty. + Self::touch_account(last_journal, &address, account); + + // Add balance to created account, as we already have target here. + let Some(new_balance) = account.info.balance.checked_add(balance) else { + self.checkpoint_revert(checkpoint); + return Err(InstructionResult::OverflowPayment); + }; + account.info.balance = new_balance; + + // EIP-161: State trie clearing (invariant-preserving alternative) + if spec_id.is_enabled_in(SPURIOUS_DRAGON) { + // nonce is going to be reset to zero in AccountCreated journal entry. + account.info.nonce = 1; + } + + // Sub balance from caller + let caller_account = self.state.get_mut(&caller).unwrap(); + // Balance is already checked in `create_inner`, so it is safe to just subtract. + caller_account.info.balance -= balance; + + // add journal entry of transferred balance + last_journal.push(JournalEntry::BalanceTransfer { + from: caller, + to: address, + balance, + }); + + Ok(checkpoint) + } + *) + Definition create_account_checkpoint (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; caller; address; balance; spec_id ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let caller := M.alloc (| caller |) in + let address := M.alloc (| address |) in + let balance := M.alloc (| balance |) in + let spec_id := M.alloc (| spec_id |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ checkpoint := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint", + [] + |), + [ M.read (| self |) ] + |) + |) in + let~ account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + address + ] + |) + ] + |) + |) in + let~ last_journal := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + LogicalOp.or (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::fixed::FixedBytes", + [ Ty.path "alloy_primitives::bits::fixed::FixedBytes" ], + "ne", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code_hash" + |); + M.get_constant (| + "revm_primitives::utilities::KECCAK_EMPTY" + |) + ] + |), + ltac:(M.monadic + (BinOp.Pure.ne + (M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |) + |)) + (Value.Integer 0))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "contains", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "warm_preloaded_addresses" + |); + address + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.never_to_any (| + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "checkpoint_revert", + [] + |), + [ M.read (| self |); M.read (| checkpoint |) ] + |) + |) in + M.return_ (| + Value.StructTuple + "core::result::Result::Err" + [ + Value.StructTuple + "revm_interpreter::instruction_result::InstructionResult::CreateCollision" + [] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "mark_created", + [] + |), + [ M.read (| account |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.read (| last_journal |); + Value.StructRecord + "revm::journaled_state::JournalEntry::AccountCreated" + [ ("address", M.read (| address |)) ] + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code" + |), + Value.StructTuple "core::option::Option::None" [] + |) in + let~ empty := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::state::StorageSlot", + [], + "default", + [] + |), + [] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "std::collections::hash::map::IterMut") + [ Ty.path "ruint::Uint"; Ty.path "revm_primitives::state::StorageSlot" ], + [], + "for_each", + [ + Ty.function + [ + Ty.tuple + [ + Ty.tuple + [ + Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ]; + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "iter_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "storage" + |) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let slot := M.copy (| ฮณ0_1 |) in + M.read (| + M.write (| + M.read (| slot |), + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "revm_primitives::state::StorageSlot", + [], + "clone", + [] + |), + [ empty ] + |) + |) + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "touch_account", + [] + |), + [ M.read (| last_journal |); address; M.read (| account |) ] + |) + |) in + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| Ty.path "ruint::Uint", "checked_add", [] |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |); + M.read (| balance |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let new_balance := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |), + M.read (| new_balance |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "is_enabled_in", + [] + |), + [ + M.read (| spec_id |); + Value.StructTuple + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + [] + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |), + Value.Integer 1 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ caller_account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + caller + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::SubAssign", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "sub_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| caller_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |); + M.read (| balance |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.read (| last_journal |); + Value.StructRecord + "revm::journaled_state::JournalEntry::BalanceTransfer" + [ + ("from", M.read (| caller |)); + ("to", M.read (| address |)); + ("balance", M.read (| balance |)) + ] + ] + |) + |) in + M.alloc (| + Value.StructTuple "core::result::Result::Ok" [ M.read (| checkpoint |) ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_create_account_checkpoint : + M.IsAssociatedFunction Self "create_account_checkpoint" create_account_checkpoint. + + (* + fn journal_revert( + state: &mut State, + transient_storage: &mut TransientStorage, + journal_entries: Vec, + is_spurious_dragon_enabled: bool, + ) { + for entry in journal_entries.into_iter().rev() { + match entry { + JournalEntry::AccountLoaded { address } => { + state.remove(&address); + } + JournalEntry::AccountTouched { address } => { + if is_spurious_dragon_enabled && address == PRECOMPILE3 { + continue; + } + // remove touched status + state.get_mut(&address).unwrap().unmark_touch(); + } + JournalEntry::AccountDestroyed { + address, + target, + was_destroyed, + had_balance, + } => { + let account = state.get_mut(&address).unwrap(); + // set previous state of selfdestructed flag, as there could be multiple + // selfdestructs in one transaction. + if was_destroyed { + // flag is still selfdestructed + account.mark_selfdestruct(); + } else { + // flag that is not selfdestructed + account.unmark_selfdestruct(); + } + account.info.balance += had_balance; + + if address != target { + let target = state.get_mut(&target).unwrap(); + target.info.balance -= had_balance; + } + } + JournalEntry::BalanceTransfer { from, to, balance } => { + // we don't need to check overflow and underflow when adding and subtracting the balance. + let from = state.get_mut(&from).unwrap(); + from.info.balance += balance; + let to = state.get_mut(&to).unwrap(); + to.info.balance -= balance; + } + JournalEntry::NonceChange { address } => { + state.get_mut(&address).unwrap().info.nonce -= 1; + } + JournalEntry::AccountCreated { address } => { + let account = &mut state.get_mut(&address).unwrap(); + account.unmark_created(); + account.info.nonce = 0; + } + JournalEntry::StorageChange { + address, + key, + had_value, + } => { + let storage = &mut state.get_mut(&address).unwrap().storage; + if let Some(had_value) = had_value { + storage.get_mut(&key).unwrap().present_value = had_value; + } else { + storage.remove(&key); + } + } + JournalEntry::TransientStorageChange { + address, + key, + had_value, + } => { + let tkey = (address, key); + if had_value == U256::ZERO { + // if previous value is zero, remove it + transient_storage.remove(&tkey); + } else { + // if not zero, reinsert old value to transient storage. + transient_storage.insert(tkey, had_value); + } + } + JournalEntry::CodeChange { address } => { + let acc = state.get_mut(&address).unwrap(); + acc.info.code_hash = KECCAK_EMPTY; + acc.info.code = None; + } + } + } + } + *) + Definition journal_revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ state; transient_storage; journal_entries; is_spurious_dragon_enabled ] => + ltac:(M.monadic + (let state := M.alloc (| state |) in + let transient_storage := M.alloc (| transient_storage |) in + let journal_entries := M.alloc (| journal_entries |) in + let is_spurious_dragon_enabled := M.alloc (| is_spurious_dragon_enabled |) in + M.read (| + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "core::iter::adapters::rev::Rev") + [ + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "into_iter", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + [], + "rev", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + [], + "into_iter", + [] + |), + [ M.read (| journal_entries |) ] + |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::rev::Rev") + [ + Ty.apply + (Ty.path "alloc::vec::into_iter::IntoIter") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| ฮณ, "core::option::Option::None" |) in + M.alloc (| M.never_to_any (| M.read (| M.break (||) |) |) |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.match_operator (| + entry, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountLoaded", + "address" + |) in + let address := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "remove", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); address ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountTouched", + "address" + |) in + let address := M.copy (| ฮณ0_0 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.and (| + M.read (| + is_spurious_dragon_enabled + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "alloy_primitives::bits::address::Address", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ], + "eq", + [] + |), + [ + address; + M.get_constant (| + "revm_primitives::constants::PRECOMPILE3" + |) + ] + |))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| M.continue (||) |) + |) + |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "unmark_touch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::Account"; + Ty.path + "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); address ] + |) + ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "address" + |) in + let ฮณ0_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "target" + |) in + let ฮณ0_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "was_destroyed" + |) in + let ฮณ0_3 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "had_balance" + |) in + let address := M.copy (| ฮณ0_0 |) in + let target := M.copy (| ฮณ0_1 |) in + let was_destroyed := M.copy (| ฮณ0_2 |) in + let had_balance := M.copy (| ฮณ0_3 |) in + let~ account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); address ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use was_destroyed in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::Account", + "mark_selfdestruct", + [] + |), + [ M.read (| account |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::Account", + "unmark_selfdestruct", + [] + |), + [ M.read (| account |) ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::AddAssign", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "add_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |); + M.read (| had_balance |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "alloy_primitives::bits::address::Address", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ], + "ne", + [] + |), + [ address; target ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ target := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::Account"; + Ty.path + "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); target ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::SubAssign", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "sub_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| target |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |); + M.read (| had_balance |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "from" + |) in + let ฮณ0_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "to" + |) in + let ฮณ0_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "balance" + |) in + let from := M.copy (| ฮณ0_0 |) in + let to := M.copy (| ฮณ0_1 |) in + let balance := M.copy (| ฮณ0_2 |) in + let~ from := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); from ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::AddAssign", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "add_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| from |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |); + M.read (| balance |) + ] + |) + |) in + let~ to := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); to ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::SubAssign", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "sub_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| to |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |); + M.read (| balance |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::NonceChange", + "address" + |) in + let address := M.copy (| ฮณ0_0 |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::Account"; + Ty.path + "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); address ] + |) + ] + |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |) in + M.write (| + ฮฒ, + BinOp.Wrap.sub + Integer.U64 + (M.read (| ฮฒ |)) + (Value.Integer 1) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountCreated", + "address" + |) in + let address := M.copy (| ฮณ0_0 |) in + let~ account := + M.alloc (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::Account"; + Ty.path + "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); address ] + |) + ] + |) + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "unmark_created", + [] + |), + [ M.read (| M.read (| account |) |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| M.read (| account |) |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "nonce" + |), + Value.Integer 0 + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "address" + |) in + let ฮณ0_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "key" + |) in + let ฮณ0_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "had_value" + |) in + let address := M.copy (| ฮณ0_0 |) in + let key := M.copy (| ฮณ0_1 |) in + let had_value := M.copy (| ฮณ0_2 |) in + let~ storage := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::Account"; + Ty.path + "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); address ] + |) + ] + |), + "revm_primitives::state::Account", + "storage" + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := had_value in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let had_value := M.copy (| ฮณ0_0 |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::StorageSlot" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "ruint::Uint" ] + |), + [ M.read (| storage |); key ] + |) + ] + |), + "revm_primitives::state::StorageSlot", + "present_value" + |), + M.read (| had_value |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "remove", + [ Ty.path "ruint::Uint" ] + |), + [ M.read (| storage |); key ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "address" + |) in + let ฮณ0_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "key" + |) in + let ฮณ0_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "had_value" + |) in + let address := M.copy (| ฮณ0_0 |) in + let key := M.copy (| ฮณ0_1 |) in + let had_value := M.copy (| ฮณ0_2 |) in + let~ tkey := + M.alloc (| + Value.Tuple + [ M.read (| address |); M.read (| key |) ] + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ + had_value; + M.get_constant (| "ruint::ZERO" |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path + "std::hash::random::RandomState" + ], + "remove", + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ] + ] + |), + [ M.read (| transient_storage |); tkey ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path + "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.read (| transient_storage |); + M.read (| tkey |); + M.read (| had_value |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::CodeChange", + "address" + |) in + let address := M.copy (| ฮณ0_0 |) in + let~ acc := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path + "alloy_primitives::bits::address::Address"; + Ty.path + "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ + Ty.path + "alloy_primitives::bits::address::Address" + ] + |), + [ M.read (| state |); address ] + |) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code_hash" + |), + M.read (| + M.get_constant (| + "revm_primitives::utilities::KECCAK_EMPTY" + |) + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code" + |), + Value.StructTuple "core::option::Option::None" [] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_journal_revert : + M.IsAssociatedFunction Self "journal_revert" journal_revert. + + (* + pub fn checkpoint(&mut self) -> JournalCheckpoint { + let checkpoint = JournalCheckpoint { + log_i: self.logs.len(), + journal_i: self.journal.len(), + }; + self.depth += 1; + self.journal.push(Default::default()); + checkpoint + } + *) + Definition checkpoint (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ checkpoint := + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalCheckpoint" + [ + ("log_i", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "logs" + |) + ] + |)); + ("journal_i", + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |)) + ] + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "depth" + |) in + M.write (| ฮฒ, BinOp.Wrap.add Integer.Usize (M.read (| ฮฒ |)) (Value.Integer 1) |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |); + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + [], + "default", + [] + |), + [] + |) + ] + |) + |) in + checkpoint + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_checkpoint : M.IsAssociatedFunction Self "checkpoint" checkpoint. + + (* + pub fn checkpoint_commit(&mut self) { + self.depth -= 1; + } + *) + Definition checkpoint_commit (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "depth" + |) in + M.write (| ฮฒ, BinOp.Wrap.sub Integer.Usize (M.read (| ฮฒ |)) (Value.Integer 1) |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_checkpoint_commit : + M.IsAssociatedFunction Self "checkpoint_commit" checkpoint_commit. + + (* + pub fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) { + let is_spurious_dragon_enabled = SpecId::enabled(self.spec, SPURIOUS_DRAGON); + let state = &mut self.state; + let transient_storage = &mut self.transient_storage; + self.depth -= 1; + // iterate over last N journals sets and revert our global state + let leng = self.journal.len(); + self.journal + .iter_mut() + .rev() + .take(leng - checkpoint.journal_i) + .for_each(|cs| { + Self::journal_revert( + state, + transient_storage, + mem::take(cs), + is_spurious_dragon_enabled, + ) + }); + + self.logs.truncate(checkpoint.log_i); + self.journal.truncate(checkpoint.journal_i); + } + *) + Definition checkpoint_revert (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; checkpoint ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let checkpoint := M.alloc (| checkpoint |) in + M.read (| + let~ is_spurious_dragon_enabled := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "enabled", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "spec" + |) + |); + Value.StructTuple "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" [] + ] + |) + |) in + let~ state := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |) + |) in + let~ transient_storage := + M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "transient_storage" + |) + |) in + let~ _ := + let ฮฒ := + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "depth" + |) in + M.write (| ฮฒ, BinOp.Wrap.sub Integer.Usize (M.read (| ฮฒ |)) (Value.Integer 1) |) in + let~ leng := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "len", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::take::Take") + [ + Ty.apply + (Ty.path "core::iter::adapters::rev::Rev") + [ + Ty.apply + (Ty.path "core::slice::iter::IterMut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ] + ], + [], + "for_each", + [ + Ty.function + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ] + ] + (Ty.tuple []) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::iter::adapters::rev::Rev") + [ + Ty.apply + (Ty.path "core::slice::iter::IterMut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + [], + "take", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::IterMut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + [], + "rev", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "iter_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + BinOp.Wrap.sub + Integer.Usize + (M.read (| leng |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + checkpoint, + "revm::journaled_state::JournalCheckpoint", + "journal_i" + |) + |)) + ] + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let cs := M.copy (| ฮณ |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "journal_revert", + [] + |), + [ + M.read (| state |); + M.read (| transient_storage |); + M.call_closure (| + M.get_function (| + "core::mem::take", + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + |), + [ M.read (| cs |) ] + |); + M.read (| is_spurious_dragon_enabled |) + ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + "truncate", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "logs" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + checkpoint, + "revm::journaled_state::JournalCheckpoint", + "log_i" + |) + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + "truncate", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |); + M.read (| + M.SubPointer.get_struct_record_field (| + checkpoint, + "revm::journaled_state::JournalCheckpoint", + "journal_i" + |) + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_checkpoint_revert : + M.IsAssociatedFunction Self "checkpoint_revert" checkpoint_revert. + + (* + pub fn selfdestruct( + &mut self, + address: Address, + target: Address, + db: &mut DB, + ) -> Result> { + let load_result = self.load_account_exist(target, db)?; + + if address != target { + // Both accounts are loaded before this point, `address` as we execute its contract. + // and `target` at the beginning of the function. + let acc_balance = self.state.get_mut(&address).unwrap().info.balance; + + let target_account = self.state.get_mut(&target).unwrap(); + Self::touch_account(self.journal.last_mut().unwrap(), &target, target_account); + target_account.info.balance += acc_balance; + } + + let acc = self.state.get_mut(&address).unwrap(); + let balance = acc.info.balance; + let previously_destroyed = acc.is_selfdestructed(); + let is_cancun_enabled = SpecId::enabled(self.spec, CANCUN); + + // EIP-6780 (Cancun hard-fork): selfdestruct only if contract is created in the same tx + let journal_entry = if acc.is_created() || !is_cancun_enabled { + acc.mark_selfdestruct(); + acc.info.balance = U256::ZERO; + Some(JournalEntry::AccountDestroyed { + address, + target, + was_destroyed: previously_destroyed, + had_balance: balance, + }) + } else if address != target { + acc.info.balance = U256::ZERO; + Some(JournalEntry::BalanceTransfer { + from: address, + to: target, + balance, + }) + } else { + // State is not changed: + // * if we are after Cancun upgrade and + // * Selfdestruct account that is created in the same transaction and + // * Specify the target is same as selfdestructed account. The balance stays unchanged. + None + }; + + if let Some(entry) = journal_entry { + self.journal.last_mut().unwrap().push(entry); + }; + + Ok(SelfDestructResult { + had_value: balance != U256::ZERO, + is_cold: load_result.is_cold, + target_exists: !load_result.is_empty, + previously_destroyed, + }) + } + *) + Definition selfdestruct (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ DB ], [ self; address; target; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let target := M.alloc (| target |) in + let db := M.alloc (| db |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ load_result := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_interpreter::host::LoadAccountResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account_exist", + [ DB ] + |), + [ M.read (| self |); M.read (| target |); M.read (| db |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_interpreter::host::SelfDestructResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "ne", + [] + |), + [ address; target ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ acc_balance := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + address + ] + |) + ] + |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |) in + let~ target_account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + target + ] + |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "touch_account", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + target; + M.read (| target_account |) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::arith::AddAssign", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "add_assign", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| target_account |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |); + M.read (| acc_balance |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ acc := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + address + ] + |) + ] + |) + |) in + let~ balance := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |) + |) in + let~ previously_destroyed := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_selfdestructed", + [] + |), + [ M.read (| acc |) ] + |) + |) in + let~ is_cancun_enabled := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "enabled", + [] + |), + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "spec" + |) + |); + Value.StructTuple "revm_primitives::specification::SpecId::CANCUN" [] + ] + |) + |) in + let~ journal_entry := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + LogicalOp.or (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_created", + [] + |), + [ M.read (| acc |) ] + |), + ltac:(M.monadic + (UnOp.Pure.not (M.read (| is_cancun_enabled |)))) + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "mark_selfdestruct", + [] + |), + [ M.read (| acc |) ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |), + M.read (| M.get_constant (| "ruint::ZERO" |) |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::journaled_state::JournalEntry::AccountDestroyed" + [ + ("address", M.read (| address |)); + ("target", M.read (| target |)); + ("was_destroyed", M.read (| previously_destroyed |)); + ("had_balance", M.read (| balance |)) + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" + ], + "ne", + [] + |), + [ address; target ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "balance" + |), + M.read (| M.get_constant (| "ruint::ZERO" |) |) + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ + Value.StructRecord + "revm::journaled_state::JournalEntry::BalanceTransfer" + [ + ("from", M.read (| address |)); + ("to", M.read (| target |)); + ("balance", M.read (| balance |)) + ] + ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + Value.StructTuple "core::option::Option::None" [] + |))) + ] + |))) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := journal_entry in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + M.read (| entry |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructRecord + "revm_interpreter::host::SelfDestructResult" + [ + ("had_value", + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ balance; M.get_constant (| "ruint::ZERO" |) ] + |)); + ("is_cold", + M.read (| + M.SubPointer.get_struct_record_field (| + load_result, + "revm_interpreter::host::LoadAccountResult", + "is_cold" + |) + |)); + ("target_exists", + UnOp.Pure.not + (M.read (| + M.SubPointer.get_struct_record_field (| + load_result, + "revm_interpreter::host::LoadAccountResult", + "is_empty" + |) + |))); + ("previously_destroyed", M.read (| previously_destroyed |)) + ] + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_selfdestruct : M.IsAssociatedFunction Self "selfdestruct" selfdestruct. + + (* + pub fn initial_account_load( + &mut self, + address: Address, + slots: &[U256], + db: &mut DB, + ) -> Result<&mut Account, EVMError> { + // load or get account. + let account = match self.state.entry(address) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(vac) => vac.insert( + db.basic(address) + .map_err(EVMError::Database)? + .map(|i| i.into()) + .unwrap_or(Account::new_not_existing()), + ), + }; + // preload storages. + for slot in slots { + if let Entry::Vacant(entry) = account.storage.entry( *slot) { + let storage = db.storage(address, *slot).map_err(EVMError::Database)?; + entry.insert(StorageSlot::new(storage)); + } + } + Ok(account) + } + *) + Definition initial_account_load (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ DB ], [ self; address; slots; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let slots := M.alloc (| slots |) in + let db := M.alloc (| db |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ account := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account" + ], + "into_mut", + [] + |), + [ M.read (| entry |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let vac := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account" + ], + "insert", + [] + |), + [ + M.read (| vac |); + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::Account" ], + "unwrap_or", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::state::AccountInfo" ], + "map", + [ + Ty.path "revm_primitives::state::Account"; + Ty.function + [ + Ty.tuple + [ Ty.path "revm_primitives::state::AccountInfo" ] + ] + (Ty.path "revm_primitives::state::Account") + ] + |), + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ]; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ]; + Ty.associated + ], + "map_err", + [ + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "basic", + [] + |), + [ M.read (| db |); M.read (| address |) ] + |); + M.constructor_as_closure + "revm_primitives::result::EVMError::Database" + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ]; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |); + M.closure + (fun ฮณ => + ltac:(M.monadic + match ฮณ with + | [ ฮฑ0 ] => + M.match_operator (| + M.alloc (| ฮฑ0 |), + [ + fun ฮณ => + ltac:(M.monadic + (let i := M.copy (| ฮณ |) in + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path + "revm_primitives::state::AccountInfo", + [ + Ty.path + "revm_primitives::state::Account" + ], + "into", + [] + |), + [ M.read (| i |) ] + |))) + ] + |) + | _ => M.impossible (||) + end)) + ] + |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "new_not_existing", + [] + |), + [] + |) + ] + |) + ] + |) + |))) + ] + |) + |) in + let~ _ := + M.use + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::collect::IntoIterator", + Ty.apply + (Ty.path "&") + [ Ty.apply (Ty.path "slice") [ Ty.path "ruint::Uint" ] ], + [], + "into_iter", + [] + |), + [ M.read (| slots |) ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let iter := M.copy (| ฮณ |) in + M.loop (| + ltac:(M.monadic + (let~ _ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::iter::traits::iterator::Iterator", + Ty.apply + (Ty.path "core::slice::iter::Iter") + [ Ty.path "ruint::Uint" ], + [], + "next", + [] + |), + [ iter ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let _ := + M.is_struct_tuple (| + ฮณ, + "core::option::Option::None" + |) in + M.alloc (| + M.never_to_any (| M.read (| M.break (||) |) |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let slot := M.copy (| ฮณ0_0 |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot"; + Ty.path + "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "storage" + |); + M.read (| M.read (| slot |) |) + ] + |) + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + let~ storage := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "ruint::Uint"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "ruint::Uint"; + Ty.associated + ], + "map_err", + [ + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "storage", + [] + |), + [ + M.read (| db |); + M.read (| address |); + M.read (| M.read (| slot |) |) + ] + |); + M.constructor_as_closure + "revm_primitives::result::EVMError::Database" + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ]; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path + "std::collections::hash::map::VacantEntry") + [ + Ty.path "ruint::Uint"; + Ty.path + "revm_primitives::state::StorageSlot" + ], + "insert", + [] + |), + [ + M.read (| entry |); + M.call_closure (| + M.get_associated_function (| + Ty.path + "revm_primitives::state::StorageSlot", + "new", + [] + |), + [ M.read (| storage |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |))) + ] + |) in + M.alloc (| Value.Tuple [] |))) + |))) + ] + |)) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ M.read (| account |) ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_initial_account_load : + M.IsAssociatedFunction Self "initial_account_load" initial_account_load. + + (* + pub fn load_account( + &mut self, + address: Address, + db: &mut DB, + ) -> Result<(&mut Account, bool), EVMError> { + Ok(match self.state.entry(address) { + Entry::Occupied(entry) => (entry.into_mut(), false), + Entry::Vacant(vac) => { + let account = + if let Some(account) = db.basic(address).map_err(EVMError::Database)? { + account.into() + } else { + Account::new_not_existing() + }; + + // journal loading of account. AccessList touch. + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::AccountLoaded { address }); + + // precompiles are warm loaded so we need to take that into account + let is_cold = !self.warm_preloaded_addresses.contains(&address); + + (vac.insert(account), is_cold) + } + }) + } + *) + Definition load_account (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ DB ], [ self; address; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let db := M.alloc (| db |) in + M.catch_return (| + ltac:(M.monadic + (Value.StructTuple + "core::result::Result::Ok" + [ + M.read (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + M.read (| address |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let entry := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.Tuple + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account" + ], + "into_mut", + [] + |), + [ M.read (| entry |) ] + |); + Value.Bool false + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let vac := M.copy (| ฮณ0_0 |) in + let~ account := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ]; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.path + "revm_primitives::state::AccountInfo" + ]; + Ty.associated + ], + "map_err", + [ + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "basic", + [] + |), + [ M.read (| db |); M.read (| address |) ] + |); + M.constructor_as_closure + "revm_primitives::result::EVMError::Database" + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let account := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::convert::Into", + Ty.path "revm_primitives::state::AccountInfo", + [ Ty.path "revm_primitives::state::Account" ], + "into", + [] + |), + [ M.read (| account |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "new_not_existing", + [] + |), + [] + |) + |))) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + Value.StructRecord + "revm::journaled_state::JournalEntry::AccountLoaded" + [ ("address", M.read (| address |)) ] + ] + |) + |) in + let~ is_cold := + M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::set::HashSet") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "std::hash::random::RandomState" + ], + "contains", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "warm_preloaded_addresses" + |); + address + ] + |)) + |) in + M.alloc (| + Value.Tuple + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account" + ], + "insert", + [] + |), + [ M.read (| vac |); M.read (| account |) ] + |); + M.read (| is_cold |) + ] + |))) + ] + |) + |) + ])) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_account : M.IsAssociatedFunction Self "load_account" load_account. + + (* + pub fn load_account_exist( + &mut self, + address: Address, + db: &mut DB, + ) -> Result> { + let spec = self.spec; + let (acc, is_cold) = self.load_account(address, db)?; + + let is_spurious_dragon_enabled = SpecId::enabled(spec, SPURIOUS_DRAGON); + let is_empty = if is_spurious_dragon_enabled { + acc.is_empty() + } else { + let loaded_not_existing = acc.is_loaded_as_not_existing(); + let is_not_touched = !acc.is_touched(); + loaded_not_existing && is_not_touched + }; + + Ok(LoadAccountResult { is_empty, is_cold }) + } + *) + Definition load_account_exist (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ DB ], [ self; address; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let db := M.alloc (| db |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ spec := + M.copy (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "spec" + |) + |) in + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ M.read (| self |); M.read (| address |); M.read (| db |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_interpreter::host::LoadAccountResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let acc := M.copy (| ฮณ0_0 |) in + let is_cold := M.copy (| ฮณ0_1 |) in + let~ is_spurious_dragon_enabled := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::specification::SpecId", + "enabled", + [] + |), + [ + M.read (| spec |); + Value.StructTuple + "revm_primitives::specification::SpecId::SPURIOUS_DRAGON" + [] + ] + |) + |) in + let~ is_empty := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use is_spurious_dragon_enabled in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_empty", + [] + |), + [ M.read (| acc |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let~ loaded_not_existing := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_loaded_as_not_existing", + [] + |), + [ M.read (| acc |) ] + |) + |) in + let~ is_not_touched := + M.alloc (| + UnOp.Pure.not + (M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_touched", + [] + |), + [ M.read (| acc |) ] + |)) + |) in + M.alloc (| + LogicalOp.and (| + M.read (| loaded_not_existing |), + ltac:(M.monadic (M.read (| is_not_touched |))) + |) + |))) + ] + |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructRecord + "revm_interpreter::host::LoadAccountResult" + [ + ("is_empty", M.read (| is_empty |)); + ("is_cold", M.read (| is_cold |)) + ] + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_account_exist : + M.IsAssociatedFunction Self "load_account_exist" load_account_exist. + + (* + pub fn load_code( + &mut self, + address: Address, + db: &mut DB, + ) -> Result<(&mut Account, bool), EVMError> { + let (acc, is_cold) = self.load_account(address, db)?; + if acc.info.code.is_none() { + if acc.info.code_hash == KECCAK_EMPTY { + let empty = Bytecode::default(); + acc.info.code = Some(empty); + } else { + let code = db + .code_by_hash(acc.info.code_hash) + .map_err(EVMError::Database)?; + acc.info.code = Some(code); + } + } + Ok((acc, is_cold)) + } + *) + Definition load_code (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ DB ], [ self; address; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let db := M.alloc (| db |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "load_account", + [ DB ] + |), + [ M.read (| self |); M.read (| address |); M.read (| db |) ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let acc := M.copy (| ฮณ0_0 |) in + let is_cold := M.copy (| ฮณ0_1 |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "revm_primitives::bytecode::Bytecode" ], + "is_none", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path + "alloy_primitives::bits::fixed::FixedBytes", + [ + Ty.path + "alloy_primitives::bits::fixed::FixedBytes" + ], + "eq", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code_hash" + |); + M.get_constant (| + "revm_primitives::utilities::KECCAK_EMPTY" + |) + ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + let~ empty := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::default::Default", + Ty.path "revm_primitives::bytecode::Bytecode", + [], + "default", + [] + |), + [] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code" + |), + Value.StructTuple + "core::option::Option::Some" + [ M.read (| empty |) ] + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => + ltac:(M.monadic + (let~ code := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_primitives::bytecode::Bytecode"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "revm_primitives::bytecode::Bytecode"; + Ty.associated + ], + "map_err", + [ + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "code_by_hash", + [] + |), + [ + M.read (| db |); + M.read (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code_hash" + |) + |) + ] + |); + M.constructor_as_closure + "revm_primitives::result::EVMError::Database" + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.path + "revm_primitives::state::Account" + ]; + Ty.path "bool" + ]; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path + "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "info" + |), + "revm_primitives::state::AccountInfo", + "code" + |), + Value.StructTuple + "core::option::Option::Some" + [ M.read (| code |) ] + |) in + M.alloc (| Value.Tuple [] |))) + ] + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ Value.Tuple [ M.read (| acc |); M.read (| is_cold |) ] ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_load_code : M.IsAssociatedFunction Self "load_code" load_code. + + (* + pub fn sload( + &mut self, + address: Address, + key: U256, + db: &mut DB, + ) -> Result<(U256, bool), EVMError> { + // assume acc is warm + let account = self.state.get_mut(&address).unwrap(); + // only if account is created in this tx we can assume that storage is empty. + let is_newly_created = account.is_created(); + let load = match account.storage.entry(key) { + Entry::Occupied(occ) => (occ.get().present_value, false), + Entry::Vacant(vac) => { + // if storage was cleared, we don't need to ping db. + let value = if is_newly_created { + U256::ZERO + } else { + db.storage(address, key).map_err(EVMError::Database)? + }; + // add it to journal as cold loaded. + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::StorageChange { + address, + key, + had_value: None, + }); + + vac.insert(StorageSlot::new(value)); + + (value, true) + } + }; + Ok(load) + } + *) + Definition sload (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ DB ], [ self; address; key; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let key := M.alloc (| key |) in + let db := M.alloc (| db |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + let~ account := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&mut") [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + address + ] + |) + ] + |) + |) in + let~ is_newly_created := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::Account", + "is_created", + [] + |), + [ M.read (| account |) ] + |) + |) in + let~ load := + M.copy (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "entry", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| account |), + "revm_primitives::state::Account", + "storage" + |); + M.read (| key |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Occupied", + 0 + |) in + let occ := M.copy (| ฮณ0_0 |) in + M.alloc (| + Value.Tuple + [ + M.read (| + M.SubPointer.get_struct_record_field (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::OccupiedEntry") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + "get", + [] + |), + [ occ ] + |), + "revm_primitives::state::StorageSlot", + "present_value" + |) + |); + Value.Bool false + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "std::collections::hash::map::Entry::Vacant", + 0 + |) in + let vac := M.copy (| ฮณ0_0 |) in + let~ value := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.use is_newly_created in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.get_constant (| "ruint::ZERO" |))); + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "ruint::Uint"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::result::Result") + [ Ty.path "ruint::Uint"; Ty.associated ], + "map_err", + [ + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]; + Ty.function + [ Ty.associated ] + (Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ]) + ] + |), + [ + M.call_closure (| + M.get_trait_method (| + "revm_primitives::db::Database", + DB, + [], + "storage", + [] + |), + [ + M.read (| db |); + M.read (| address |); + M.read (| key |) + ] + |); + M.constructor_as_closure + "revm_primitives::result::EVMError::Database" + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple + [ + Ty.path "ruint::Uint"; + Ty.path "bool" + ]; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path + "core::convert::Infallible"; + Ty.apply + (Ty.path + "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |))) + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path + "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + Value.StructRecord + "revm::journaled_state::JournalEntry::StorageChange" + [ + ("address", M.read (| address |)); + ("key", M.read (| key |)); + ("had_value", + Value.StructTuple "core::option::Option::None" []) + ] + ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::VacantEntry") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot" + ], + "insert", + [] + |), + [ + M.read (| vac |); + M.call_closure (| + M.get_associated_function (| + Ty.path "revm_primitives::state::StorageSlot", + "new", + [] + |), + [ M.read (| value |) ] + |) + ] + |) + |) in + M.alloc (| Value.Tuple [ M.read (| value |); Value.Bool true ] |))) + ] + |) + |) in + M.alloc (| Value.StructTuple "core::result::Result::Ok" [ M.read (| load |) ] |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_sload : M.IsAssociatedFunction Self "sload" sload. + + (* + pub fn sstore( + &mut self, + address: Address, + key: U256, + new: U256, + db: &mut DB, + ) -> Result> { + // assume that acc exists and load the slot. + let (present, is_cold) = self.sload(address, key, db)?; + let acc = self.state.get_mut(&address).unwrap(); + + // if there is no original value in dirty return present value, that is our original. + let slot = acc.storage.get_mut(&key).unwrap(); + + // new value is same as present, we don't need to do anything + if present == new { + return Ok(SStoreResult { + original_value: slot.previous_or_original_value, + present_value: present, + new_value: new, + is_cold, + }); + } + + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::StorageChange { + address, + key, + had_value: Some(present), + }); + // insert value into present state. + slot.present_value = new; + Ok(SStoreResult { + original_value: slot.previous_or_original_value, + present_value: present, + new_value: new, + is_cold, + }) + } + *) + Definition sstore (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ DB ], [ self; address; key; new; db ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let key := M.alloc (| key |) in + let new := M.alloc (| new |) in + let db := M.alloc (| db |) in + M.catch_return (| + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.match_operator (| + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::Try", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.tuple [ Ty.path "ruint::Uint"; Ty.path "bool" ]; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [], + "branch", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.path "revm::journaled_state::JournaledState", + "sload", + [ DB ] + |), + [ + M.read (| self |); + M.read (| address |); + M.read (| key |); + M.read (| db |) + ] + |) + ] + |) + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Break", + 0 + |) in + let residual := M.copy (| ฮณ0_0 |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + M.call_closure (| + M.get_trait_method (| + "core::ops::try_trait::FromResidual", + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "revm_interpreter::host::SStoreResult"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ], + [ + Ty.apply + (Ty.path "core::result::Result") + [ + Ty.path "core::convert::Infallible"; + Ty.apply + (Ty.path "revm_primitives::result::EVMError") + [ Ty.associated ] + ] + ], + "from_residual", + [] + |), + [ M.read (| residual |) ] + |) + |) + |) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::ops::control_flow::ControlFlow::Continue", + 0 + |) in + let val := M.copy (| ฮณ0_0 |) in + val)) + ] + |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let present := M.copy (| ฮณ0_0 |) in + let is_cold := M.copy (| ฮณ0_1 |) in + let~ acc := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::Account" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "revm_primitives::state::Account"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "alloy_primitives::bits::address::Address" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "state" + |); + address + ] + |) + ] + |) + |) in + let~ slot := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ Ty.path "revm_primitives::state::StorageSlot" ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.path "ruint::Uint"; + Ty.path "revm_primitives::state::StorageSlot"; + Ty.path "std::hash::random::RandomState" + ], + "get_mut", + [ Ty.path "ruint::Uint" ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| acc |), + "revm_primitives::state::Account", + "storage" + |); + key + ] + |) + ] + |) + |) in + let~ _ := + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ present; new ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + M.never_to_any (| + M.read (| + M.return_ (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructRecord + "revm_interpreter::host::SStoreResult" + [ + ("original_value", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| slot |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |) + |)); + ("present_value", M.read (| present |)); + ("new_value", M.read (| new |)); + ("is_cold", M.read (| is_cold |)) + ] + ] + |) + |) + |) + |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + Value.StructRecord + "revm::journaled_state::JournalEntry::StorageChange" + [ + ("address", M.read (| address |)); + ("key", M.read (| key |)); + ("had_value", + Value.StructTuple + "core::option::Option::Some" + [ M.read (| present |) ]) + ] + ] + |) + |) in + let~ _ := + M.write (| + M.SubPointer.get_struct_record_field (| + M.read (| slot |), + "revm_primitives::state::StorageSlot", + "present_value" + |), + M.read (| new |) + |) in + M.alloc (| + Value.StructTuple + "core::result::Result::Ok" + [ + Value.StructRecord + "revm_interpreter::host::SStoreResult" + [ + ("original_value", + M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| slot |), + "revm_primitives::state::StorageSlot", + "previous_or_original_value" + |) + |)); + ("present_value", M.read (| present |)); + ("new_value", M.read (| new |)); + ("is_cold", M.read (| is_cold |)) + ] + ] + |))) + ] + |) + |))) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_sstore : M.IsAssociatedFunction Self "sstore" sstore. + + (* + pub fn tload(&mut self, address: Address, key: U256) -> U256 { + self.transient_storage + .get(&(address, key)) + .copied() + .unwrap_or_default() + } + *) + Definition tload (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; key ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let key := M.alloc (| key |) in + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ Ty.apply (Ty.path "&") [ Ty.path "ruint::Uint" ] ], + "copied", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "get", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "transient_storage" + |); + M.alloc (| Value.Tuple [ M.read (| address |); M.read (| key |) ] |) + ] + |) + ] + |) + ] + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_tload : M.IsAssociatedFunction Self "tload" tload. + + (* + pub fn tstore(&mut self, address: Address, key: U256, new: U256) { + let had_value = if new == U256::ZERO { + // if new values is zero, remove entry from transient storage. + // if previous values was some insert it inside journal. + // If it is none nothing should be inserted. + self.transient_storage.remove(&(address, key)) + } else { + // insert values + let previous_value = self + .transient_storage + .insert((address, key), new) + .unwrap_or_default(); + + // check if previous value is same + if previous_value != new { + // if it is different, insert previous values inside journal. + Some(previous_value) + } else { + None + } + }; + + if let Some(had_value) = had_value { + // insert in journal only if value was changed. + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::TransientStorageChange { + address, + key, + had_value, + }); + } + } + *) + Definition tstore (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; address; key; new ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let address := M.alloc (| address |) in + let key := M.alloc (| key |) in + let new := M.alloc (| new |) in + M.read (| + let~ had_value := + M.copy (| + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ new; M.get_constant (| "ruint::ZERO" |) ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| M.read (| ฮณ |), Value.Bool true |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "remove", + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ] + ] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "transient_storage" + |); + M.alloc (| Value.Tuple [ M.read (| address |); M.read (| key |) ] |) + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let~ previous_value := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + "unwrap_or_default", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "std::collections::hash::map::HashMap") + [ + Ty.tuple + [ + Ty.path "alloy_primitives::bits::address::Address"; + Ty.path "ruint::Uint" + ]; + Ty.path "ruint::Uint"; + Ty.path "std::hash::random::RandomState" + ], + "insert", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "transient_storage" + |); + Value.Tuple [ M.read (| address |); M.read (| key |) ]; + M.read (| new |) + ] + |) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := + M.use + (M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "ne", + [] + |), + [ previous_value; new ] + |) + |)) in + let _ := + M.is_constant_or_break_match (| + M.read (| ฮณ |), + Value.Bool true + |) in + M.alloc (| + Value.StructTuple + "core::option::Option::Some" + [ M.read (| previous_value |) ] + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| Value.StructTuple "core::option::Option::None" [] |))) + ] + |))) + ] + |) + |) in + M.match_operator (| + M.alloc (| Value.Tuple [] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := had_value in + let ฮณ0_0 := + M.SubPointer.get_struct_tuple_field (| + ฮณ, + "core::option::Option::Some", + 0 + |) in + let had_value := M.copy (| ฮณ0_0 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "core::option::Option") + [ + Ty.apply + (Ty.path "&mut") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ] + ], + "unwrap", + [] + |), + [ + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "slice") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ] + ], + "last_mut", + [] + |), + [ + M.call_closure (| + M.get_trait_method (| + "core::ops::deref::DerefMut", + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.path "revm::journaled_state::JournalEntry"; + Ty.path "alloc::alloc::Global" + ]; + Ty.path "alloc::alloc::Global" + ], + [], + "deref_mut", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "journal" + |) + ] + |) + ] + |) + ] + |); + Value.StructRecord + "revm::journaled_state::JournalEntry::TransientStorageChange" + [ + ("address", M.read (| address |)); + ("key", M.read (| key |)); + ("had_value", M.read (| had_value |)) + ] + ] + |) + |) in + M.alloc (| Value.Tuple [] |))); + fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_tstore : M.IsAssociatedFunction Self "tstore" tstore. + + (* + pub fn log(&mut self, log: Log) { + self.logs.push(log); + } + *) + Definition log (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; log ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let log := M.alloc (| log |) in + M.read (| + let~ _ := + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.apply + (Ty.path "alloc::vec::Vec") + [ + Ty.apply + (Ty.path "alloy_primitives::log::Log") + [ Ty.path "alloy_primitives::log::LogData" ]; + Ty.path "alloc::alloc::Global" + ], + "push", + [] + |), + [ + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournaledState", + "logs" + |); + M.read (| log |) + ] + |) + |) in + M.alloc (| Value.Tuple [] |) + |))) + | _, _ => M.impossible + end. + + Axiom AssociatedFunction_log : M.IsAssociatedFunction Self "log" log. + End Impl_revm_journaled_state_JournaledState. + + (* + Enum JournalEntry + { + ty_params := []; + variants := + [ + { + name := "AccountLoaded"; + item := StructRecord [ ("address", Ty.path "alloy_primitives::bits::address::Address") ]; + discriminant := None; + }; + { + name := "AccountDestroyed"; + item := + StructRecord + [ + ("address", Ty.path "alloy_primitives::bits::address::Address"); + ("target", Ty.path "alloy_primitives::bits::address::Address"); + ("was_destroyed", Ty.path "bool"); + ("had_balance", Ty.path "ruint::Uint") + ]; + discriminant := None; + }; + { + name := "AccountTouched"; + item := StructRecord [ ("address", Ty.path "alloy_primitives::bits::address::Address") ]; + discriminant := None; + }; + { + name := "BalanceTransfer"; + item := + StructRecord + [ + ("from", Ty.path "alloy_primitives::bits::address::Address"); + ("to", Ty.path "alloy_primitives::bits::address::Address"); + ("balance", Ty.path "ruint::Uint") + ]; + discriminant := None; + }; + { + name := "NonceChange"; + item := StructRecord [ ("address", Ty.path "alloy_primitives::bits::address::Address") ]; + discriminant := None; + }; + { + name := "AccountCreated"; + item := StructRecord [ ("address", Ty.path "alloy_primitives::bits::address::Address") ]; + discriminant := None; + }; + { + name := "StorageChange"; + item := + StructRecord + [ + ("address", Ty.path "alloy_primitives::bits::address::Address"); + ("key", Ty.path "ruint::Uint"); + ("had_value", Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ]) + ]; + discriminant := None; + }; + { + name := "TransientStorageChange"; + item := + StructRecord + [ + ("address", Ty.path "alloy_primitives::bits::address::Address"); + ("key", Ty.path "ruint::Uint"); + ("had_value", Ty.path "ruint::Uint") + ]; + discriminant := None; + }; + { + name := "CodeChange"; + item := StructRecord [ ("address", Ty.path "alloy_primitives::bits::address::Address") ]; + discriminant := None; + } + ]; + } + *) + + Module Impl_core_fmt_Debug_for_revm_journaled_state_JournalEntry. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalEntry". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountLoaded", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "AccountLoaded" |); + M.read (| Value.String "address" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "address" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "target" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "was_destroyed" + |) in + let ฮณ1_3 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "had_balance" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + let __self_3 := M.alloc (| ฮณ1_3 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field4_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "AccountDestroyed" |); + M.read (| Value.String "address" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "target" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_1 |)); + M.read (| Value.String "was_destroyed" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_2 |)); + M.read (| Value.String "had_balance" |); + (* Unsize *) M.pointer_coercion __self_3 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountTouched", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "AccountTouched" |); + M.read (| Value.String "address" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "from" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "to" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "balance" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "BalanceTransfer" |); + M.read (| Value.String "from" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "to" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_1 |)); + M.read (| Value.String "balance" |); + (* Unsize *) M.pointer_coercion __self_2 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::NonceChange", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "NonceChange" |); + M.read (| Value.String "address" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountCreated", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "AccountCreated" |); + M.read (| Value.String "address" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "address" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "key" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "had_value" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "StorageChange" |); + M.read (| Value.String "address" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "key" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_1 |)); + M.read (| Value.String "had_value" |); + (* Unsize *) M.pointer_coercion __self_2 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "address" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "key" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "had_value" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field3_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "TransientStorageChange" |); + M.read (| Value.String "address" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_0 |)); + M.read (| Value.String "key" |); + (* Unsize *) M.pointer_coercion (M.read (| __self_1 |)); + M.read (| Value.String "had_value" |); + (* Unsize *) M.pointer_coercion __self_2 + ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::CodeChange", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field1_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "CodeChange" |); + M.read (| Value.String "address" |); + (* Unsize *) M.pointer_coercion __self_0 + ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_journaled_state_JournalEntry. + + Module Impl_core_clone_Clone_for_revm_journaled_state_JournalEntry. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalEntry". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountLoaded", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalEntry::AccountLoaded" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "address" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "target" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "was_destroyed" + |) in + let ฮณ1_3 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "had_balance" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + let __self_3 := M.alloc (| ฮณ1_3 |) in + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalEntry::AccountDestroyed" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("target", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)); + ("was_destroyed", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "bool", + [], + "clone", + [] + |), + [ M.read (| __self_2 |) ] + |)); + ("had_balance", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ M.read (| __self_3 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountTouched", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalEntry::AccountTouched" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "from" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "to" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "balance" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalEntry::BalanceTransfer" + [ + ("from", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("to", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)); + ("balance", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ M.read (| __self_2 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::NonceChange", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalEntry::NonceChange" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountCreated", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalEntry::AccountCreated" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "address" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "key" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "had_value" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalEntry::StorageChange" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("key", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)); + ("had_value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + [], + "clone", + [] + |), + [ M.read (| __self_2 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "address" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "key" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "had_value" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalEntry::TransientStorageChange" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)); + ("key", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ M.read (| __self_1 |) ] + |)); + ("had_value", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "ruint::Uint", + [], + "clone", + [] + |), + [ M.read (| __self_2 |) ] + |)) + ] + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::CodeChange", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + Value.StructRecord + "revm::journaled_state::JournalEntry::CodeChange" + [ + ("address", + M.call_closure (| + M.get_trait_method (| + "core::clone::Clone", + Ty.path "alloy_primitives::bits::address::Address", + [], + "clone", + [] + |), + [ M.read (| __self_0 |) ] + |)) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_journaled_state_JournalEntry. + + Module Impl_core_marker_StructuralPartialEq_for_revm_journaled_state_JournalEntry. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalEntry". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_journaled_state_JournalEntry. + + Module Impl_core_cmp_PartialEq_for_revm_journaled_state_JournalEntry. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalEntry". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::journaled_state::JournalEntry" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ __arg1_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::journaled_state::JournalEntry" ] + |), + [ M.read (| other |) ] + |) + |) in + M.alloc (| + LogicalOp.and (| + BinOp.Pure.eq (M.read (| __self_tag |)) (M.read (| __arg1_tag |)), + ltac:(M.monadic + (M.read (| + M.match_operator (| + M.alloc (| Value.Tuple [ M.read (| self |); M.read (| other |) ] |), + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountLoaded", + "address" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::AccountLoaded", + "address" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "address" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "target" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "was_destroyed" + |) in + let ฮณ2_3 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "had_balance" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let __self_2 := M.alloc (| ฮณ2_2 |) in + let __self_3 := M.alloc (| ฮณ2_3 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "address" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "target" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "was_destroyed" + |) in + let ฮณ2_3 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "had_balance" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + let __arg1_2 := M.alloc (| ฮณ2_2 |) in + let __arg1_3 := M.alloc (| ฮณ2_3 |) in + M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_1 |); M.read (| __arg1_1 |) ] + |))) + |), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| M.read (| __self_2 |) |)) + (M.read (| M.read (| __arg1_2 |) |)))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| __self_3 |); M.read (| __arg1_3 |) ] + |))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountTouched", + "address" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::AccountTouched", + "address" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "from" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "to" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "balance" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let __self_2 := M.alloc (| ฮณ2_2 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "from" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "to" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "balance" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + let __arg1_2 := M.alloc (| ฮณ2_2 |) in + M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_1 |); M.read (| __arg1_1 |) ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| __self_2 |); M.read (| __arg1_2 |) ] + |))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::NonceChange", + "address" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::NonceChange", + "address" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::AccountCreated", + "address" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::AccountCreated", + "address" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::StorageChange", + "address" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::StorageChange", + "key" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::StorageChange", + "had_value" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let __self_2 := M.alloc (| ฮณ2_2 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::StorageChange", + "address" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::StorageChange", + "key" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::StorageChange", + "had_value" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + let __arg1_2 := M.alloc (| ฮณ2_2 |) in + M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| __self_1 |); M.read (| __arg1_1 |) ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ], + [ + Ty.apply + (Ty.path "core::option::Option") + [ Ty.path "ruint::Uint" ] + ], + "eq", + [] + |), + [ M.read (| __self_2 |); M.read (| __arg1_2 |) ] + |))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "address" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "key" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "had_value" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let __self_1 := M.alloc (| ฮณ2_1 |) in + let __self_2 := M.alloc (| ฮณ2_2 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "address" + |) in + let ฮณ2_1 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "key" + |) in + let ฮณ2_2 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "had_value" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + let __arg1_1 := M.alloc (| ฮณ2_1 |) in + let __arg1_2 := M.alloc (| ฮณ2_2 |) in + M.alloc (| + LogicalOp.and (| + LogicalOp.and (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| __self_1 |); M.read (| __arg1_1 |) ] + |))) + |), + ltac:(M.monadic + (M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "ruint::Uint", + [ Ty.path "ruint::Uint" ], + "eq", + [] + |), + [ M.read (| __self_2 |); M.read (| __arg1_2 |) ] + |))) + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ0_0 := M.SubPointer.get_tuple_field (| ฮณ, 0 |) in + let ฮณ0_1 := M.SubPointer.get_tuple_field (| ฮณ, 1 |) in + let ฮณ0_0 := M.read (| ฮณ0_0 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_0, + "revm::journaled_state::JournalEntry::CodeChange", + "address" + |) in + let __self_0 := M.alloc (| ฮณ2_0 |) in + let ฮณ0_1 := M.read (| ฮณ0_1 |) in + let ฮณ2_0 := + M.SubPointer.get_struct_record_field (| + ฮณ0_1, + "revm::journaled_state::JournalEntry::CodeChange", + "address" + |) in + let __arg1_0 := M.alloc (| ฮณ2_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::cmp::PartialEq", + Ty.path "alloy_primitives::bits::address::Address", + [ Ty.path "alloy_primitives::bits::address::Address" ], + "eq", + [] + |), + [ M.read (| __self_0 |); M.read (| __arg1_0 |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (M.alloc (| + M.never_to_any (| + M.call_closure (| + M.get_function (| "core::intrinsics::unreachable", [] |), + [] + |) + |) + |))) + ] + |) + |))) + |) + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_journaled_state_JournalEntry. + + Module Impl_core_marker_StructuralEq_for_revm_journaled_state_JournalEntry. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalEntry". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_journaled_state_JournalEntry. + + Module Impl_core_cmp_Eq_for_revm_journaled_state_JournalEntry. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalEntry". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ + fun ฮณ => + ltac:(M.monadic + (M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |))) + ] + |))) + ] + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_journaled_state_JournalEntry. + + Module Impl_core_hash_Hash_for_revm_journaled_state_JournalEntry. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalEntry". + + (* Hash *) + Definition hash (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [ __H ], [ self; state ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let state := M.alloc (| state |) in + M.read (| + let~ __self_tag := + M.alloc (| + M.call_closure (| + M.get_function (| + "core::intrinsics::discriminant_value", + [ Ty.path "revm::journaled_state::JournalEntry" ] + |), + [ M.read (| self |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| "core::hash::Hash", Ty.path "isize", [], "hash", [ __H ] |), + [ __self_tag; M.read (| state |) ] + |) + |) in + M.match_operator (| + self, + [ + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountLoaded", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "address" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "target" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "was_destroyed" + |) in + let ฮณ1_3 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountDestroyed", + "had_balance" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + let __self_3 := M.alloc (| ฮณ1_3 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "bool", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_2 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_3 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountTouched", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "from" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "to" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::BalanceTransfer", + "balance" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_2 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::NonceChange", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::AccountCreated", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "address" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "key" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::StorageChange", + "had_value" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.apply (Ty.path "core::option::Option") [ Ty.path "ruint::Uint" ], + [], + "hash", + [ __H ] + |), + [ M.read (| __self_2 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "address" + |) in + let ฮณ1_1 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "key" + |) in + let ฮณ1_2 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::TransientStorageChange", + "had_value" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + let __self_1 := M.alloc (| ฮณ1_1 |) in + let __self_2 := M.alloc (| ฮณ1_2 |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |) in + let~ _ := + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_1 |); M.read (| state |) ] + |) + |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "ruint::Uint", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_2 |); M.read (| state |) ] + |) + |))); + fun ฮณ => + ltac:(M.monadic + (let ฮณ := M.read (| ฮณ |) in + let ฮณ1_0 := + M.SubPointer.get_struct_record_field (| + ฮณ, + "revm::journaled_state::JournalEntry::CodeChange", + "address" + |) in + let __self_0 := M.alloc (| ฮณ1_0 |) in + M.alloc (| + M.call_closure (| + M.get_trait_method (| + "core::hash::Hash", + Ty.path "alloy_primitives::bits::address::Address", + [], + "hash", + [ __H ] + |), + [ M.read (| __self_0 |); M.read (| state |) ] + |) + |))) + ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::hash::Hash" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("hash", InstanceField.Method hash) ]. + End Impl_core_hash_Hash_for_revm_journaled_state_JournalEntry. + + (* StructRecord + { + name := "JournalCheckpoint"; + ty_params := []; + fields := [ ("log_i", Ty.path "usize"); ("journal_i", Ty.path "usize") ]; + } *) + + Module Impl_core_fmt_Debug_for_revm_journaled_state_JournalCheckpoint. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalCheckpoint". + + (* Debug *) + Definition fmt (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; f ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let f := M.alloc (| f |) in + M.call_closure (| + M.get_associated_function (| + Ty.path "core::fmt::Formatter", + "debug_struct_field2_finish", + [] + |), + [ + M.read (| f |); + M.read (| Value.String "JournalCheckpoint" |); + M.read (| Value.String "log_i" |); + (* Unsize *) + M.pointer_coercion + (M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournalCheckpoint", + "log_i" + |)); + M.read (| Value.String "journal_i" |); + (* Unsize *) + M.pointer_coercion + (M.alloc (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournalCheckpoint", + "journal_i" + |) + |)) + ] + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::fmt::Debug" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("fmt", InstanceField.Method fmt) ]. + End Impl_core_fmt_Debug_for_revm_journaled_state_JournalCheckpoint. + + Module Impl_core_marker_Copy_for_revm_journaled_state_JournalCheckpoint. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalCheckpoint". + + Axiom Implements : + M.IsTraitInstance + "core::marker::Copy" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_Copy_for_revm_journaled_state_JournalCheckpoint. + + Module Impl_core_clone_Clone_for_revm_journaled_state_JournalCheckpoint. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalCheckpoint". + + (* Clone *) + Definition clone (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.read (| self |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::clone::Clone" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("clone", InstanceField.Method clone) ]. + End Impl_core_clone_Clone_for_revm_journaled_state_JournalCheckpoint. + + Module Impl_core_marker_StructuralPartialEq_for_revm_journaled_state_JournalCheckpoint. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalCheckpoint". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralPartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralPartialEq_for_revm_journaled_state_JournalCheckpoint. + + Module Impl_core_cmp_PartialEq_for_revm_journaled_state_JournalCheckpoint. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalCheckpoint". + + (* PartialEq *) + Definition eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self; other ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + let other := M.alloc (| other |) in + LogicalOp.and (| + BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournalCheckpoint", + "log_i" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::journaled_state::JournalCheckpoint", + "log_i" + |) + |)), + ltac:(M.monadic + (BinOp.Pure.eq + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| self |), + "revm::journaled_state::JournalCheckpoint", + "journal_i" + |) + |)) + (M.read (| + M.SubPointer.get_struct_record_field (| + M.read (| other |), + "revm::journaled_state::JournalCheckpoint", + "journal_i" + |) + |)))) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::PartialEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) [ ("eq", InstanceField.Method eq) ]. + End Impl_core_cmp_PartialEq_for_revm_journaled_state_JournalCheckpoint. + + Module Impl_core_marker_StructuralEq_for_revm_journaled_state_JournalCheckpoint. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalCheckpoint". + + Axiom Implements : + M.IsTraitInstance + "core::marker::StructuralEq" + Self + (* Trait polymorphic types *) [] + (* Instance *) []. + End Impl_core_marker_StructuralEq_for_revm_journaled_state_JournalCheckpoint. + + Module Impl_core_cmp_Eq_for_revm_journaled_state_JournalCheckpoint. + Definition Self : Ty.t := Ty.path "revm::journaled_state::JournalCheckpoint". + + (* Eq *) + Definition assert_receiver_is_total_eq (ฯ„ : list Ty.t) (ฮฑ : list Value.t) : M := + match ฯ„, ฮฑ with + | [], [ self ] => + ltac:(M.monadic + (let self := M.alloc (| self |) in + M.read (| + M.match_operator (| + Value.DeclaredButUndefined, + [ fun ฮณ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |))) ] + |) + |))) + | _, _ => M.impossible + end. + + Axiom Implements : + M.IsTraitInstance + "core::cmp::Eq" + Self + (* Trait polymorphic types *) [] + (* Instance *) + [ ("assert_receiver_is_total_eq", InstanceField.Method assert_receiver_is_total_eq) ]. + End Impl_core_cmp_Eq_for_revm_journaled_state_JournalCheckpoint. +End journaled_state. +``` diff --git a/docs/revm-python-spec/revm-verif/revm-verif.md b/docs/revm-python-spec/revm-verif/revm-verif.md new file mode 100644 index 00000000..278f0c79 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm-verif.md @@ -0,0 +1,7 @@ +# Revm Verification + +The goal of this project is to formally verify the [Rust implementation of the EVM](https://github.com/bluealloy/revm) by showing that it is equivalent to the [Python specification of the EVM](https://github.com/ethereum/execution-specs). + +We use the [Coq](https://coq.inria.fr/) proof assistant to do the proofs. We use [coq-of-rust](https://github.com/formal-land/coq-of-rust) to convert the Rust code to Coq, and [coq-of-python](https://github.com/formal-land/coq-of-python) to convert the Python code to Coq. + +Here we present the list of Rust, Python and Coq files from the project. Most of Coq files are automatically generated from the source files, and we have a beginning of simulation files and proofs. diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/function_stack.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/function_stack.md new file mode 100644 index 00000000..1a17361e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/function_stack.md @@ -0,0 +1,70 @@ +# ๐Ÿฆ€ function_stack.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/function_stack.rs) + +```rust +use std::vec::Vec; + +/// Function return frame. +/// Needed information for returning from a function. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct FunctionReturnFrame { + /// The index of the code container that this frame is executing. + pub idx: usize, + /// The program counter where frame execution should continue. + pub pc: usize, +} + +impl FunctionReturnFrame { + /// Return new function frame. + pub fn new(idx: usize, pc: usize) -> Self { + Self { idx, pc } + } +} + +/// Function Stack +#[derive(Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct FunctionStack { + pub return_stack: Vec, + pub current_code_idx: usize, +} + +impl FunctionStack { + /// Returns new function stack. + pub fn new() -> Self { + Self { + return_stack: Vec::new(), + current_code_idx: 0, + } + } + + /// Pushes a new frame to the stack. and sets current_code_idx to new value. + pub fn push(&mut self, program_counter: usize, new_idx: usize) { + self.return_stack.push(FunctionReturnFrame { + idx: self.current_code_idx, + pc: program_counter, + }); + self.current_code_idx = new_idx; + } + + /// Return stack length + pub fn return_stack_len(&self) -> usize { + self.return_stack.len() + } + + /// Pops a frame from the stack and sets current_code_idx to the popped frame's idx. + pub fn pop(&mut self) -> Option { + self.return_stack.pop().map(|frame| { + self.current_code_idx = frame.idx; + frame + }) + } + + /// Sets current_code_idx, this is needed for JUMPF opcode. + pub fn set_current_code_idx(&mut self, idx: usize) { + self.current_code_idx = idx; + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/gas.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/gas.md new file mode 100644 index 00000000..6064b13a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/gas.md @@ -0,0 +1,139 @@ +# ๐Ÿฆ€ gas.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/gas.rs) + +```rust +//! EVM gas calculation utilities. + +mod calc; +mod constants; + +pub use calc::*; +pub use constants::*; + +/// Represents the state of gas during execution. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Gas { + /// The initial gas limit. This is constant throughout execution. + limit: u64, + /// The remaining gas. + remaining: u64, + /// Refunded gas. This is used only at the end of execution. + refunded: i64, +} + +impl Gas { + /// Creates a new `Gas` struct with the given gas limit. + #[inline] + pub const fn new(limit: u64) -> Self { + Self { + limit, + remaining: limit, + refunded: 0, + } + } + + /// Creates a new `Gas` struct with the given gas limit, but without any gas remaining. + #[inline] + pub const fn new_spent(limit: u64) -> Self { + Self { + limit, + remaining: 0, + refunded: 0, + } + } + + /// Returns the gas limit. + #[inline] + pub const fn limit(&self) -> u64 { + self.limit + } + + /// Returns the **last** memory expansion cost. + #[inline] + #[deprecated = "memory expansion cost is not tracked anymore; \ + calculate it using `SharedMemory::current_expansion_cost` instead"] + #[doc(hidden)] + pub const fn memory(&self) -> u64 { + 0 + } + + /// Returns the total amount of gas that was refunded. + #[inline] + pub const fn refunded(&self) -> i64 { + self.refunded + } + + /// Returns the total amount of gas spent. + #[inline] + pub const fn spent(&self) -> u64 { + self.limit - self.remaining + } + + #[doc(hidden)] + #[inline] + #[deprecated(note = "use `spent` instead")] + pub const fn spend(&self) -> u64 { + self.spent() + } + + /// Returns the amount of gas remaining. + #[inline] + pub const fn remaining(&self) -> u64 { + self.remaining + } + + /// Erases a gas cost from the totals. + #[inline] + pub fn erase_cost(&mut self, returned: u64) { + self.remaining += returned; + } + + /// Spends all remaining gas. + #[inline] + pub fn spend_all(&mut self) { + self.remaining = 0; + } + + /// Records a refund value. + /// + /// `refund` can be negative but `self.refunded` should always be positive + /// at the end of transact. + #[inline] + pub fn record_refund(&mut self, refund: i64) { + self.refunded += refund; + } + + /// Set a refund value for final refund. + /// + /// Max refund value is limited to Nth part (depending of fork) of gas spend. + /// + /// Related to EIP-3529: Reduction in refunds + #[inline] + pub fn set_final_refund(&mut self, is_london: bool) { + let max_refund_quotient = if is_london { 5 } else { 2 }; + self.refunded = (self.refunded() as u64).min(self.spent() / max_refund_quotient) as i64; + } + + /// Set a refund value. This overrides the current refund value. + #[inline] + pub fn set_refund(&mut self, refund: i64) { + self.refunded = refund; + } + + /// Records an explicit cost. + /// + /// Returns `false` if the gas limit is exceeded. + #[inline] + #[must_use] + pub fn record_cost(&mut self, cost: u64) -> bool { + let (remaining, overflow) = self.remaining.overflowing_sub(cost); + let success = !overflow; + if success { + self.remaining = remaining; + } + success + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/gas/calc.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/gas/calc.md new file mode 100644 index 00000000..4da6e786 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/gas/calc.md @@ -0,0 +1,418 @@ +# ๐Ÿฆ€ calc.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/gas/calc.rs) + +```rust +use super::constants::*; +use crate::{ + num_words, + primitives::{Address, Bytes, SpecId, U256}, + SelfDestructResult, +}; +use std::vec::Vec; + +/// `const` Option `?`. +macro_rules! tri { + ($e:expr) => { + match $e { + Some(v) => v, + None => return None, + } + }; +} + +/// `SSTORE` opcode refund calculation. +#[allow(clippy::collapsible_else_if)] +#[inline] +pub fn sstore_refund(spec_id: SpecId, original: U256, current: U256, new: U256) -> i64 { + if spec_id.is_enabled_in(SpecId::ISTANBUL) { + // EIP-3529: Reduction in refunds + let sstore_clears_schedule = if spec_id.is_enabled_in(SpecId::LONDON) { + (SSTORE_RESET - COLD_SLOAD_COST + ACCESS_LIST_STORAGE_KEY) as i64 + } else { + REFUND_SSTORE_CLEARS + }; + if current == new { + 0 + } else { + if original == current && new == U256::ZERO { + sstore_clears_schedule + } else { + let mut refund = 0; + + if original != U256::ZERO { + if current == U256::ZERO { + refund -= sstore_clears_schedule; + } else if new == U256::ZERO { + refund += sstore_clears_schedule; + } + } + + if original == new { + let (gas_sstore_reset, gas_sload) = if spec_id.is_enabled_in(SpecId::BERLIN) { + (SSTORE_RESET - COLD_SLOAD_COST, WARM_STORAGE_READ_COST) + } else { + (SSTORE_RESET, sload_cost(spec_id, false)) + }; + if original == U256::ZERO { + refund += (SSTORE_SET - gas_sload) as i64; + } else { + refund += (gas_sstore_reset - gas_sload) as i64; + } + } + + refund + } + } + } else { + if current != U256::ZERO && new == U256::ZERO { + REFUND_SSTORE_CLEARS + } else { + 0 + } + } +} + +/// `CREATE2` opcode cost calculation. +#[inline] +pub const fn create2_cost(len: u64) -> Option { + CREATE.checked_add(tri!(cost_per_word(len, KECCAK256WORD))) +} + +#[inline] +const fn log2floor(value: U256) -> u64 { + let mut l: u64 = 256; + let mut i = 3; + loop { + if value.as_limbs()[i] == 0u64 { + l -= 64; + } else { + l -= value.as_limbs()[i].leading_zeros() as u64; + if l == 0 { + return l; + } else { + return l - 1; + } + } + if i == 0 { + break; + } + i -= 1; + } + l +} + +/// `EXP` opcode cost calculation. +#[inline] +pub fn exp_cost(spec_id: SpecId, power: U256) -> Option { + if power == U256::ZERO { + Some(EXP) + } else { + // EIP-160: EXP cost increase + let gas_byte = U256::from(if spec_id.is_enabled_in(SpecId::SPURIOUS_DRAGON) { + 50 + } else { + 10 + }); + let gas = U256::from(EXP) + .checked_add(gas_byte.checked_mul(U256::from(log2floor(power) / 8 + 1))?)?; + + u64::try_from(gas).ok() + } +} + +/// `*COPY` opcodes cost calculation. +#[inline] +pub const fn verylowcopy_cost(len: u64) -> Option { + VERYLOW.checked_add(tri!(cost_per_word(len, COPY))) +} + +/// `EXTCODECOPY` opcode cost calculation. +#[inline] +pub const fn extcodecopy_cost(spec_id: SpecId, len: u64, is_cold: bool) -> Option { + let base_gas = if spec_id.is_enabled_in(SpecId::BERLIN) { + warm_cold_cost(is_cold) + } else if spec_id.is_enabled_in(SpecId::TANGERINE) { + 700 + } else { + 20 + }; + base_gas.checked_add(tri!(cost_per_word(len, COPY))) +} + +/// `LOG` opcode cost calculation. +#[inline] +pub const fn log_cost(n: u8, len: u64) -> Option { + tri!(LOG.checked_add(tri!(LOGDATA.checked_mul(len)))).checked_add(LOGTOPIC * n as u64) +} + +/// `KECCAK256` opcode cost calculation. +#[inline] +pub const fn keccak256_cost(len: u64) -> Option { + KECCAK256.checked_add(tri!(cost_per_word(len, KECCAK256WORD))) +} + +/// Calculate the cost of buffer per word. +#[inline] +pub const fn cost_per_word(len: u64, multiple: u64) -> Option { + multiple.checked_mul(num_words(len)) +} + +/// EIP-3860: Limit and meter initcode +/// +/// Apply extra gas cost of 2 for every 32-byte chunk of initcode. +/// +/// This cannot overflow as the initcode length is assumed to be checked. +#[inline] +pub const fn initcode_cost(len: u64) -> u64 { + let Some(cost) = cost_per_word(len, INITCODE_WORD_COST) else { + panic!("initcode cost overflow") + }; + cost +} + +/// `SLOAD` opcode cost calculation. +#[inline] +pub const fn sload_cost(spec_id: SpecId, is_cold: bool) -> u64 { + if spec_id.is_enabled_in(SpecId::BERLIN) { + if is_cold { + COLD_SLOAD_COST + } else { + WARM_STORAGE_READ_COST + } + } else if spec_id.is_enabled_in(SpecId::ISTANBUL) { + // EIP-1884: Repricing for trie-size-dependent opcodes + INSTANBUL_SLOAD_GAS + } else if spec_id.is_enabled_in(SpecId::TANGERINE) { + // EIP-150: Gas cost changes for IO-heavy operations + 200 + } else { + 50 + } +} + +/// `SSTORE` opcode cost calculation. +#[inline] +pub fn sstore_cost( + spec_id: SpecId, + original: U256, + current: U256, + new: U256, + gas: u64, + is_cold: bool, +) -> Option { + // EIP-1706 Disable SSTORE with gasleft lower than call stipend + if spec_id.is_enabled_in(SpecId::ISTANBUL) && gas <= CALL_STIPEND { + return None; + } + + if spec_id.is_enabled_in(SpecId::BERLIN) { + // Berlin specification logic + let mut gas_cost = istanbul_sstore_cost::( + original, current, new, + ); + + if is_cold { + gas_cost += COLD_SLOAD_COST; + } + Some(gas_cost) + } else if spec_id.is_enabled_in(SpecId::ISTANBUL) { + // Istanbul logic + Some(istanbul_sstore_cost::( + original, current, new, + )) + } else { + // Frontier logic + Some(frontier_sstore_cost(current, new)) + } +} + +/// EIP-2200: Structured Definitions for Net Gas Metering +#[inline] +fn istanbul_sstore_cost( + original: U256, + current: U256, + new: U256, +) -> u64 { + if new == current { + SLOAD_GAS + } else if original == current && original == U256::ZERO { + SSTORE_SET + } else if original == current { + SSTORE_RESET_GAS + } else { + SLOAD_GAS + } +} + +/// Frontier sstore cost just had two cases set and reset values. +#[inline] +fn frontier_sstore_cost(current: U256, new: U256) -> u64 { + if current == U256::ZERO && new != U256::ZERO { + SSTORE_SET + } else { + SSTORE_RESET + } +} + +/// `SELFDESTRUCT` opcode cost calculation. +#[inline] +pub const fn selfdestruct_cost(spec_id: SpecId, res: SelfDestructResult) -> u64 { + // EIP-161: State trie clearing (invariant-preserving alternative) + let should_charge_topup = if spec_id.is_enabled_in(SpecId::SPURIOUS_DRAGON) { + res.had_value && !res.target_exists + } else { + !res.target_exists + }; + + // EIP-150: Gas cost changes for IO-heavy operations + let selfdestruct_gas_topup = if spec_id.is_enabled_in(SpecId::TANGERINE) && should_charge_topup + { + 25000 + } else { + 0 + }; + + // EIP-150: Gas cost changes for IO-heavy operations + let selfdestruct_gas = if spec_id.is_enabled_in(SpecId::TANGERINE) { + 5000 + } else { + 0 + }; + + let mut gas = selfdestruct_gas + selfdestruct_gas_topup; + if spec_id.is_enabled_in(SpecId::BERLIN) && res.is_cold { + gas += COLD_ACCOUNT_ACCESS_COST + } + gas +} + +/// Calculate call gas cost for the call instruction. +/// +/// There is three types of gas. +/// * Account access gas. after berlin it can be cold or warm. +/// * Transfer value gas. If value is transferred and balance of target account is updated. +/// * If account is not existing and needs to be created. After Spurious dragon +/// this is only accounted if value is transferred. +#[inline] +pub const fn call_cost( + spec_id: SpecId, + transfers_value: bool, + is_cold: bool, + new_account_accounting: bool, +) -> u64 { + // Account access. + let mut gas = if spec_id.is_enabled_in(SpecId::BERLIN) { + warm_cold_cost(is_cold) + } else if spec_id.is_enabled_in(SpecId::TANGERINE) { + // EIP-150: Gas cost changes for IO-heavy operations + 700 + } else { + 40 + }; + + // transfer value cost + if transfers_value { + gas += CALLVALUE; + } + + // new account cost + if new_account_accounting { + // EIP-161: State trie clearing (invariant-preserving alternative) + if spec_id.is_enabled_in(SpecId::SPURIOUS_DRAGON) { + // account only if there is value transferred. + if transfers_value { + gas += NEWACCOUNT; + } + } else { + gas += NEWACCOUNT; + } + } + + gas +} + +/// Berlin warm and cold storage access cost for account access. +#[inline] +pub const fn warm_cold_cost(is_cold: bool) -> u64 { + if is_cold { + COLD_ACCOUNT_ACCESS_COST + } else { + WARM_STORAGE_READ_COST + } +} + +/// Memory expansion cost calculation for a given memory length. +#[inline] +pub const fn memory_gas_for_len(len: usize) -> u64 { + memory_gas(crate::interpreter::num_words(len as u64)) +} + +/// Memory expansion cost calculation for a given number of words. +#[inline] +pub const fn memory_gas(num_words: u64) -> u64 { + MEMORY + .saturating_mul(num_words) + .saturating_add(num_words.saturating_mul(num_words) / 512) +} + +/// Initial gas that is deducted for transaction to be included. +/// Initial gas contains initial stipend gas, gas for access list and input data. +pub fn validate_initial_tx_gas( + spec_id: SpecId, + input: &[u8], + is_create: bool, + access_list: &[(Address, Vec)], + initcodes: &[Bytes], +) -> u64 { + let mut initial_gas = 0; + let mut zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; + let mut non_zero_data_len = input.len() as u64 - zero_data_len; + + // Enabling of initcode is checked in `validate_env` handler. + for initcode in initcodes { + let zeros = initcode.iter().filter(|v| **v == 0).count() as u64; + zero_data_len += zeros; + non_zero_data_len += initcode.len() as u64 - zeros; + } + + // initdate stipend + initial_gas += zero_data_len * TRANSACTION_ZERO_DATA; + // EIP-2028: Transaction data gas cost reduction + initial_gas += non_zero_data_len + * if spec_id.is_enabled_in(SpecId::ISTANBUL) { + 16 + } else { + 68 + }; + + // get number of access list account and storages. + if spec_id.is_enabled_in(SpecId::BERLIN) { + let accessed_slots = access_list + .iter() + .fold(0, |slot_count, (_, slots)| slot_count + slots.len() as u64); + initial_gas += access_list.len() as u64 * ACCESS_LIST_ADDRESS; + initial_gas += accessed_slots * ACCESS_LIST_STORAGE_KEY; + } + + // base stipend + initial_gas += if is_create { + if spec_id.is_enabled_in(SpecId::HOMESTEAD) { + // EIP-2: Homestead Hard-fork Changes + 53000 + } else { + 21000 + } + } else { + 21000 + }; + + // EIP-3860: Limit and meter initcode + // Initcode stipend for bytecode analysis + if spec_id.is_enabled_in(SpecId::SHANGHAI) && is_create { + initial_gas += initcode_cost(input.len() as u64) + } + + initial_gas +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/gas/constants.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/gas/constants.md new file mode 100644 index 00000000..e1c3927f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/gas/constants.md @@ -0,0 +1,59 @@ +# ๐Ÿฆ€ constants.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/gas/constants.rs) + +```rust +pub const ZERO: u64 = 0; +pub const BASE: u64 = 2; + +pub const VERYLOW: u64 = 3; +pub const DATA_LOADN_GAS: u64 = 3; + +pub const CONDITION_JUMP_GAS: u64 = 4; +pub const RETF_GAS: u64 = 4; +pub const DATA_LOAD_GAS: u64 = 4; + +pub const LOW: u64 = 5; +pub const MID: u64 = 8; +pub const HIGH: u64 = 10; +pub const JUMPDEST: u64 = 1; +pub const SELFDESTRUCT: i64 = 24000; +pub const CREATE: u64 = 32000; +pub const CALLVALUE: u64 = 9000; +pub const NEWACCOUNT: u64 = 25000; +pub const EXP: u64 = 10; +pub const MEMORY: u64 = 3; +pub const LOG: u64 = 375; +pub const LOGDATA: u64 = 8; +pub const LOGTOPIC: u64 = 375; +pub const KECCAK256: u64 = 30; +pub const KECCAK256WORD: u64 = 6; +pub const COPY: u64 = 3; +pub const BLOCKHASH: u64 = 20; +pub const CODEDEPOSIT: u64 = 200; + +/// EIP-1884: Repricing for trie-size-dependent opcodes +pub const INSTANBUL_SLOAD_GAS: u64 = 800; +pub const SSTORE_SET: u64 = 20000; +pub const SSTORE_RESET: u64 = 5000; +pub const REFUND_SSTORE_CLEARS: i64 = 15000; + +pub const TRANSACTION_ZERO_DATA: u64 = 4; +pub const TRANSACTION_NON_ZERO_DATA_INIT: u64 = 16; +pub const TRANSACTION_NON_ZERO_DATA_FRONTIER: u64 = 68; + +pub const EOF_CREATE_GAS: u64 = 32000; + +// berlin eip2929 constants +pub const ACCESS_LIST_ADDRESS: u64 = 2400; +pub const ACCESS_LIST_STORAGE_KEY: u64 = 1900; +pub const COLD_SLOAD_COST: u64 = 2100; +pub const COLD_ACCOUNT_ACCESS_COST: u64 = 2600; +pub const WARM_STORAGE_READ_COST: u64 = 100; +pub const WARM_SSTORE_RESET: u64 = SSTORE_RESET - COLD_SLOAD_COST; + +/// EIP-3860 : Limit and meter initcode +pub const INITCODE_WORD_COST: u64 = 2; + +pub const CALL_STIPEND: u64 = 2300; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/host.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/host.md new file mode 100644 index 00000000..18c158fa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/host.md @@ -0,0 +1,102 @@ +# ๐Ÿฆ€ host.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/host.rs) + +```rust +use crate::primitives::{Address, Bytecode, Env, Log, B256, U256}; + +mod dummy; +pub use dummy::DummyHost; + +/// EVM context host. +pub trait Host { + /// Returns a reference to the environment. + fn env(&self) -> &Env; + + /// Returns a mutable reference to the environment. + fn env_mut(&mut self) -> &mut Env; + + /// Load an account. + /// + /// Returns (is_cold, is_new_account) + fn load_account(&mut self, address: Address) -> Option; + + /// Get the block hash of the given block `number`. + fn block_hash(&mut self, number: U256) -> Option; + + /// Get balance of `address` and if the account is cold. + fn balance(&mut self, address: Address) -> Option<(U256, bool)>; + + /// Get code of `address` and if the account is cold. + fn code(&mut self, address: Address) -> Option<(Bytecode, bool)>; + + /// Get code hash of `address` and if the account is cold. + fn code_hash(&mut self, address: Address) -> Option<(B256, bool)>; + + /// Get storage value of `address` at `index` and if the account is cold. + fn sload(&mut self, address: Address, index: U256) -> Option<(U256, bool)>; + + /// Set storage value of account address at index. + /// + /// Returns (original, present, new, is_cold). + fn sstore(&mut self, address: Address, index: U256, value: U256) -> Option; + + /// Get the transient storage value of `address` at `index`. + fn tload(&mut self, address: Address, index: U256) -> U256; + + /// Set the transient storage value of `address` at `index`. + fn tstore(&mut self, address: Address, index: U256, value: U256); + + /// Emit a log owned by `address` with given `LogData`. + fn log(&mut self, log: Log); + + /// Mark `address` to be deleted, with funds transferred to `target`. + fn selfdestruct(&mut self, address: Address, target: Address) -> Option; +} + +/// Represents the result of an `sstore` operation. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SStoreResult { + /// Value of the storage when it is first read + pub original_value: U256, + /// Current value of the storage + pub present_value: U256, + /// New value that is set + pub new_value: U256, + /// Is storage slot loaded from database + pub is_cold: bool, +} + +/// Result of the account load from Journal state. +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct LoadAccountResult { + /// Is account cold loaded + pub is_cold: bool, + /// Is account empty, if true account is not created. + pub is_empty: bool, +} + +/// Result of a selfdestruct instruction. +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SelfDestructResult { + pub had_value: bool, + pub target_exists: bool, + pub is_cold: bool, + pub previously_destroyed: bool, +} + +#[cfg(test)] +mod tests { + use super::*; + + fn assert_host() {} + + #[test] + fn object_safety() { + assert_host::(); + assert_host::(); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/host/dummy.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/host/dummy.md new file mode 100644 index 00000000..0781cfef --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/host/dummy.md @@ -0,0 +1,130 @@ +# ๐Ÿฆ€ dummy.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/host/dummy.rs) + +```rust +use crate::primitives::{hash_map::Entry, Bytecode, HashMap, U256}; +use crate::{ + primitives::{Address, Env, Log, B256, KECCAK_EMPTY}, + Host, SStoreResult, SelfDestructResult, +}; +use std::vec::Vec; + +use super::LoadAccountResult; + +/// A dummy [Host] implementation. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct DummyHost { + pub env: Env, + pub storage: HashMap, + pub transient_storage: HashMap, + pub log: Vec, +} + +impl DummyHost { + /// Create a new dummy host with the given [`Env`]. + #[inline] + pub fn new(env: Env) -> Self { + Self { + env, + ..Default::default() + } + } + + /// Clears the storage and logs of the dummy host. + #[inline] + pub fn clear(&mut self) { + self.storage.clear(); + self.log.clear(); + } +} + +impl Host for DummyHost { + #[inline] + fn env(&self) -> &Env { + &self.env + } + + #[inline] + fn env_mut(&mut self) -> &mut Env { + &mut self.env + } + + #[inline] + fn load_account(&mut self, _address: Address) -> Option { + Some(LoadAccountResult::default()) + } + + #[inline] + fn block_hash(&mut self, _number: U256) -> Option { + Some(B256::ZERO) + } + + #[inline] + fn balance(&mut self, _address: Address) -> Option<(U256, bool)> { + Some((U256::ZERO, false)) + } + + #[inline] + fn code(&mut self, _address: Address) -> Option<(Bytecode, bool)> { + Some((Bytecode::default(), false)) + } + + #[inline] + fn code_hash(&mut self, __address: Address) -> Option<(B256, bool)> { + Some((KECCAK_EMPTY, false)) + } + + #[inline] + fn sload(&mut self, __address: Address, index: U256) -> Option<(U256, bool)> { + match self.storage.entry(index) { + Entry::Occupied(entry) => Some((*entry.get(), false)), + Entry::Vacant(entry) => { + entry.insert(U256::ZERO); + Some((U256::ZERO, true)) + } + } + } + + #[inline] + fn sstore(&mut self, _address: Address, index: U256, value: U256) -> Option { + let (present, is_cold) = match self.storage.entry(index) { + Entry::Occupied(mut entry) => (entry.insert(value), false), + Entry::Vacant(entry) => { + entry.insert(value); + (U256::ZERO, true) + } + }; + + Some(SStoreResult { + original_value: U256::ZERO, + present_value: present, + new_value: value, + is_cold, + }) + } + + #[inline] + fn tload(&mut self, _address: Address, index: U256) -> U256 { + self.transient_storage + .get(&index) + .copied() + .unwrap_or_default() + } + + #[inline] + fn tstore(&mut self, _address: Address, index: U256, value: U256) { + self.transient_storage.insert(index, value); + } + + #[inline] + fn log(&mut self, log: Log) { + self.log.push(log) + } + + #[inline] + fn selfdestruct(&mut self, _address: Address, _target: Address) -> Option { + panic!("Selfdestruct is not supported for this host") + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instruction_result.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instruction_result.md new file mode 100644 index 00000000..449ceb48 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instruction_result.md @@ -0,0 +1,357 @@ +# ๐Ÿฆ€ instruction_result.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instruction_result.rs) + +```rust +use crate::primitives::{HaltReason, OutOfGasError, SuccessReason}; + +#[repr(u8)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum InstructionResult { + // success codes + #[default] + Continue = 0x00, + Stop, + Return, + SelfDestruct, + ReturnContract, + + // revert codes + Revert = 0x10, // revert opcode + CallTooDeep, + OutOfFunds, + + // Actions + CallOrCreate = 0x20, + + // error codes + OutOfGas = 0x50, + MemoryOOG, + MemoryLimitOOG, + PrecompileOOG, + InvalidOperandOOG, + OpcodeNotFound, + CallNotAllowedInsideStatic, + StateChangeDuringStaticCall, + InvalidFEOpcode, + InvalidJump, + NotActivated, + StackUnderflow, + StackOverflow, + OutOfOffset, + CreateCollision, + OverflowPayment, + PrecompileError, + NonceOverflow, + /// Create init code size exceeds limit (runtime). + CreateContractSizeLimit, + /// Error on created contract that begins with EF + CreateContractStartingWithEF, + /// EIP-3860: Limit and meter initcode. Initcode size limit exceeded. + CreateInitCodeSizeLimit, + /// Fatal external error. Returned by database. + FatalExternalError, + /// RETURNCONTRACT called in not init eof code. + ReturnContractInNotInitEOF, + /// Legacy contract is calling opcode that is enabled only in EOF. + EOFOpcodeDisabledInLegacy, + /// EOF function stack overflow + EOFFunctionStackOverflow, +} + +impl From for InstructionResult { + fn from(value: SuccessReason) -> Self { + match value { + SuccessReason::Return => InstructionResult::Return, + SuccessReason::Stop => InstructionResult::Stop, + SuccessReason::SelfDestruct => InstructionResult::SelfDestruct, + } + } +} + +impl From for InstructionResult { + fn from(value: HaltReason) -> Self { + match value { + HaltReason::OutOfGas(error) => match error { + OutOfGasError::Basic => Self::OutOfGas, + OutOfGasError::InvalidOperand => Self::InvalidOperandOOG, + OutOfGasError::Memory => Self::MemoryOOG, + OutOfGasError::MemoryLimit => Self::MemoryLimitOOG, + OutOfGasError::Precompile => Self::PrecompileOOG, + }, + HaltReason::OpcodeNotFound => Self::OpcodeNotFound, + HaltReason::InvalidFEOpcode => Self::InvalidFEOpcode, + HaltReason::InvalidJump => Self::InvalidJump, + HaltReason::NotActivated => Self::NotActivated, + HaltReason::StackOverflow => Self::StackOverflow, + HaltReason::StackUnderflow => Self::StackUnderflow, + HaltReason::OutOfOffset => Self::OutOfOffset, + HaltReason::CreateCollision => Self::CreateCollision, + HaltReason::PrecompileError => Self::PrecompileError, + HaltReason::NonceOverflow => Self::NonceOverflow, + HaltReason::CreateContractSizeLimit => Self::CreateContractSizeLimit, + HaltReason::CreateContractStartingWithEF => Self::CreateContractStartingWithEF, + HaltReason::CreateInitCodeSizeLimit => Self::CreateInitCodeSizeLimit, + HaltReason::OverflowPayment => Self::OverflowPayment, + HaltReason::StateChangeDuringStaticCall => Self::StateChangeDuringStaticCall, + HaltReason::CallNotAllowedInsideStatic => Self::CallNotAllowedInsideStatic, + HaltReason::OutOfFunds => Self::OutOfFunds, + HaltReason::CallTooDeep => Self::CallTooDeep, + #[cfg(feature = "optimism")] + HaltReason::FailedDeposit => Self::FatalExternalError, + } + } +} + +#[macro_export] +macro_rules! return_ok { + () => { + InstructionResult::Continue + | InstructionResult::Stop + | InstructionResult::Return + | InstructionResult::SelfDestruct + | InstructionResult::ReturnContract + }; +} + +#[macro_export] +macro_rules! return_revert { + () => { + InstructionResult::Revert | InstructionResult::CallTooDeep | InstructionResult::OutOfFunds + }; +} + +#[macro_export] +macro_rules! return_error { + () => { + InstructionResult::OutOfGas + | InstructionResult::MemoryOOG + | InstructionResult::MemoryLimitOOG + | InstructionResult::PrecompileOOG + | InstructionResult::InvalidOperandOOG + | InstructionResult::OpcodeNotFound + | InstructionResult::CallNotAllowedInsideStatic + | InstructionResult::StateChangeDuringStaticCall + | InstructionResult::InvalidFEOpcode + | InstructionResult::InvalidJump + | InstructionResult::NotActivated + | InstructionResult::StackUnderflow + | InstructionResult::StackOverflow + | InstructionResult::OutOfOffset + | InstructionResult::CreateCollision + | InstructionResult::OverflowPayment + | InstructionResult::PrecompileError + | InstructionResult::NonceOverflow + | InstructionResult::CreateContractSizeLimit + | InstructionResult::CreateContractStartingWithEF + | InstructionResult::CreateInitCodeSizeLimit + | InstructionResult::FatalExternalError + | InstructionResult::ReturnContractInNotInitEOF + | InstructionResult::EOFOpcodeDisabledInLegacy + | InstructionResult::EOFFunctionStackOverflow + }; +} + +impl InstructionResult { + /// Returns whether the result is a success. + #[inline] + pub const fn is_ok(self) -> bool { + matches!(self, crate::return_ok!()) + } + + /// Returns whether the result is a revert. + #[inline] + pub const fn is_revert(self) -> bool { + matches!(self, crate::return_revert!()) + } + + /// Returns whether the result is an error. + #[inline] + pub const fn is_error(self) -> bool { + matches!(self, return_error!()) + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum SuccessOrHalt { + Success(SuccessReason), + Revert, + Halt(HaltReason), + FatalExternalError, + /// Internal instruction that signals Interpreter should continue running. + InternalContinue, + /// Internal instruction that signals call or create. + InternalCallOrCreate, +} + +impl SuccessOrHalt { + /// Returns true if the transaction returned successfully without halts. + #[inline] + pub fn is_success(self) -> bool { + matches!(self, SuccessOrHalt::Success(_)) + } + + /// Returns the [SuccessReason] value if this a successful result + #[inline] + pub fn to_success(self) -> Option { + match self { + SuccessOrHalt::Success(reason) => Some(reason), + _ => None, + } + } + + /// Returns true if the transaction reverted. + #[inline] + pub fn is_revert(self) -> bool { + matches!(self, SuccessOrHalt::Revert) + } + + /// Returns true if the EVM has experienced an exceptional halt + #[inline] + pub fn is_halt(self) -> bool { + matches!(self, SuccessOrHalt::Halt(_)) + } + + /// Returns the [HaltReason] value the EVM has experienced an exceptional halt + #[inline] + pub fn to_halt(self) -> Option { + match self { + SuccessOrHalt::Halt(reason) => Some(reason), + _ => None, + } + } +} + +impl From for SuccessOrHalt { + fn from(result: InstructionResult) -> Self { + match result { + InstructionResult::Continue => Self::InternalContinue, // used only in interpreter loop + InstructionResult::Stop => Self::Success(SuccessReason::Stop), + InstructionResult::Return => Self::Success(SuccessReason::Return), + InstructionResult::SelfDestruct => Self::Success(SuccessReason::SelfDestruct), + InstructionResult::Revert => Self::Revert, + InstructionResult::CallOrCreate => Self::InternalCallOrCreate, // used only in interpreter loop + InstructionResult::CallTooDeep => Self::Halt(HaltReason::CallTooDeep), // not gonna happen for first call + InstructionResult::OutOfFunds => Self::Halt(HaltReason::OutOfFunds), // Check for first call is done separately. + InstructionResult::OutOfGas => Self::Halt(HaltReason::OutOfGas(OutOfGasError::Basic)), + InstructionResult::MemoryLimitOOG => { + Self::Halt(HaltReason::OutOfGas(OutOfGasError::MemoryLimit)) + } + InstructionResult::MemoryOOG => Self::Halt(HaltReason::OutOfGas(OutOfGasError::Memory)), + InstructionResult::PrecompileOOG => { + Self::Halt(HaltReason::OutOfGas(OutOfGasError::Precompile)) + } + InstructionResult::InvalidOperandOOG => { + Self::Halt(HaltReason::OutOfGas(OutOfGasError::InvalidOperand)) + } + InstructionResult::OpcodeNotFound | InstructionResult::ReturnContractInNotInitEOF => { + Self::Halt(HaltReason::OpcodeNotFound) + } + InstructionResult::CallNotAllowedInsideStatic => { + Self::Halt(HaltReason::CallNotAllowedInsideStatic) + } // first call is not static call + InstructionResult::StateChangeDuringStaticCall => { + Self::Halt(HaltReason::StateChangeDuringStaticCall) + } + InstructionResult::InvalidFEOpcode => Self::Halt(HaltReason::InvalidFEOpcode), + InstructionResult::InvalidJump => Self::Halt(HaltReason::InvalidJump), + InstructionResult::NotActivated => Self::Halt(HaltReason::NotActivated), + InstructionResult::StackUnderflow => Self::Halt(HaltReason::StackUnderflow), + InstructionResult::StackOverflow => Self::Halt(HaltReason::StackOverflow), + InstructionResult::OutOfOffset => Self::Halt(HaltReason::OutOfOffset), + InstructionResult::CreateCollision => Self::Halt(HaltReason::CreateCollision), + InstructionResult::OverflowPayment => Self::Halt(HaltReason::OverflowPayment), // Check for first call is done separately. + InstructionResult::PrecompileError => Self::Halt(HaltReason::PrecompileError), + InstructionResult::NonceOverflow => Self::Halt(HaltReason::NonceOverflow), + InstructionResult::CreateContractSizeLimit + | InstructionResult::CreateContractStartingWithEF => { + Self::Halt(HaltReason::CreateContractSizeLimit) + } + InstructionResult::CreateInitCodeSizeLimit => { + Self::Halt(HaltReason::CreateInitCodeSizeLimit) + } + InstructionResult::FatalExternalError => Self::FatalExternalError, + InstructionResult::EOFOpcodeDisabledInLegacy => Self::Halt(HaltReason::OpcodeNotFound), + InstructionResult::EOFFunctionStackOverflow => Self::FatalExternalError, + InstructionResult::ReturnContract => { + panic!("Unexpected EOF internal Return Contract") + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::InstructionResult; + + #[test] + fn all_results_are_covered() { + match InstructionResult::Continue { + return_error!() => {} + return_revert!() => {} + return_ok!() => {} + InstructionResult::CallOrCreate => {} + } + } + + #[test] + fn test_results() { + let ok_results = vec![ + InstructionResult::Continue, + InstructionResult::Stop, + InstructionResult::Return, + InstructionResult::SelfDestruct, + ]; + + for result in ok_results { + assert!(result.is_ok()); + assert!(!result.is_revert()); + assert!(!result.is_error()); + } + + let revert_results = vec![ + InstructionResult::Revert, + InstructionResult::CallTooDeep, + InstructionResult::OutOfFunds, + ]; + + for result in revert_results { + assert!(!result.is_ok()); + assert!(result.is_revert()); + assert!(!result.is_error()); + } + + let error_results = vec![ + InstructionResult::OutOfGas, + InstructionResult::MemoryOOG, + InstructionResult::MemoryLimitOOG, + InstructionResult::PrecompileOOG, + InstructionResult::InvalidOperandOOG, + InstructionResult::OpcodeNotFound, + InstructionResult::CallNotAllowedInsideStatic, + InstructionResult::StateChangeDuringStaticCall, + InstructionResult::InvalidFEOpcode, + InstructionResult::InvalidJump, + InstructionResult::NotActivated, + InstructionResult::StackUnderflow, + InstructionResult::StackOverflow, + InstructionResult::OutOfOffset, + InstructionResult::CreateCollision, + InstructionResult::OverflowPayment, + InstructionResult::PrecompileError, + InstructionResult::NonceOverflow, + InstructionResult::CreateContractSizeLimit, + InstructionResult::CreateContractStartingWithEF, + InstructionResult::CreateInitCodeSizeLimit, + InstructionResult::FatalExternalError, + ]; + + for result in error_results { + assert!(!result.is_ok()); + assert!(!result.is_revert()); + assert!(result.is_error()); + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions.md new file mode 100644 index 00000000..a18a5216 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions.md @@ -0,0 +1,22 @@ +# ๐Ÿฆ€ instructions.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions.rs) + +```rust +//! EVM opcode implementations. + +#[macro_use] +pub mod macros; +pub mod arithmetic; +pub mod bitwise; +pub mod contract; +pub mod control; +pub mod data; +pub mod host; +pub mod host_env; +pub mod i256; +pub mod memory; +pub mod stack; +pub mod system; +pub mod utility; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/arithmetic.md new file mode 100644 index 00000000..601659c4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/arithmetic.md @@ -0,0 +1,104 @@ +# ๐Ÿฆ€ arithmetic.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/arithmetic.rs) + +```rust +use super::i256::{i256_div, i256_mod}; +use crate::{ + gas, + primitives::{Spec, U256}, + Host, Interpreter, +}; + +pub fn add(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1.wrapping_add(*op2); +} + +pub fn mul(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + *op2 = op1.wrapping_mul(*op2); +} + +pub fn sub(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1.wrapping_sub(*op2); +} + +pub fn div(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + if *op2 != U256::ZERO { + *op2 = op1.wrapping_div(*op2); + } +} + +pub fn sdiv(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + *op2 = i256_div(op1, *op2); +} + +pub fn rem(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + if *op2 != U256::ZERO { + *op2 = op1.wrapping_rem(*op2); + } +} + +pub fn smod(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, op1, op2); + *op2 = i256_mod(op1, *op2) +} + +pub fn addmod(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::MID); + pop_top!(interpreter, op1, op2, op3); + *op3 = op1.add_mod(op2, *op3) +} + +pub fn mulmod(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::MID); + pop_top!(interpreter, op1, op2, op3); + *op3 = op1.mul_mod(op2, *op3) +} + +pub fn exp(interpreter: &mut Interpreter, _host: &mut H) { + pop_top!(interpreter, op1, op2); + gas_or_fail!(interpreter, gas::exp_cost(SPEC::SPEC_ID, *op2)); + *op2 = op1.pow(*op2); +} + +/// In the yellow paper `SIGNEXTEND` is defined to take two inputs, we will call them +/// `x` and `y`, and produce one output. The first `t` bits of the output (numbering from the +/// left, starting from 0) are equal to the `t`-th bit of `y`, where `t` is equal to +/// `256 - 8(x + 1)`. The remaining bits of the output are equal to the corresponding bits of `y`. +/// Note: if `x >= 32` then the output is equal to `y` since `t <= 0`. To efficiently implement +/// this algorithm in the case `x < 32` we do the following. Let `b` be equal to the `t`-th bit +/// of `y` and let `s = 255 - t = 8x + 7` (this is effectively the same index as `t`, but +/// numbering the bits from the right instead of the left). We can create a bit mask which is all +/// zeros up to and including the `t`-th bit, and all ones afterwards by computing the quantity +/// `2^s - 1`. We can use this mask to compute the output depending on the value of `b`. +/// If `b == 1` then the yellow paper says the output should be all ones up to +/// and including the `t`-th bit, followed by the remaining bits of `y`; this is equal to +/// `y | !mask` where `|` is the bitwise `OR` and `!` is bitwise negation. Similarly, if +/// `b == 0` then the yellow paper says the output should start with all zeros, then end with +/// bits from `b`; this is equal to `y & mask` where `&` is bitwise `AND`. +pub fn signextend(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::LOW); + pop_top!(interpreter, ext, x); + // For 31 we also don't need to do anything. + if ext < U256::from(31) { + let ext = ext.as_limbs()[0]; + let bit_index = (8 * ext + 7) as usize; + let bit = x.bit(bit_index); + let mask = (U256::from(1) << bit_index) - U256::from(1); + *x = if bit { *x | !mask } else { *x & mask }; + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/bitwise.md new file mode 100644 index 00000000..b0e567fe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/bitwise.md @@ -0,0 +1,408 @@ +# ๐Ÿฆ€ bitwise.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/bitwise.rs) + +```rust +use super::i256::{i256_cmp, i256_sign_compl, two_compl, Sign}; +use crate::{ + gas, + primitives::{Spec, U256}, + Host, Interpreter, +}; +use core::cmp::Ordering; +use revm_primitives::uint; + +pub fn lt(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(op1 < *op2); +} + +pub fn gt(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(op1 > *op2); +} + +pub fn slt(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less); +} + +pub fn sgt(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater); +} + +pub fn eq(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = U256::from(op1 == *op2); +} + +pub fn iszero(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1); + *op1 = U256::from(*op1 == U256::ZERO); +} + +pub fn bitand(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1 & *op2; +} + +pub fn bitor(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1 | *op2; +} + +pub fn bitxor(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 = op1 ^ *op2; +} + +pub fn not(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1); + *op1 = !*op1; +} + +pub fn byte(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + + let o1 = as_usize_saturated!(op1); + *op2 = if o1 < 32 { + // `31 - o1` because `byte` returns LE, while we want BE + U256::from(op2.byte(31 - o1)) + } else { + U256::ZERO + }; +} + +/// EIP-145: Bitwise shifting instructions in EVM +pub fn shl(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, CONSTANTINOPLE); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 <<= as_usize_saturated!(op1); +} + +/// EIP-145: Bitwise shifting instructions in EVM +pub fn shr(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, CONSTANTINOPLE); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + *op2 >>= as_usize_saturated!(op1); +} + +/// EIP-145: Bitwise shifting instructions in EVM +pub fn sar(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, CONSTANTINOPLE); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, op1, op2); + + let value_sign = i256_sign_compl(op2); + + // If the shift count is 255+, we can short-circuit. This is because shifting by 255 bits is the + // maximum shift that still leaves 1 bit in the original 256-bit number. Shifting by 256 bits or + // more would mean that no original bits remain. The result depends on what the highest bit of + // the value is. + *op2 = if value_sign == Sign::Zero || op1 >= U256::from(255) { + match value_sign { + // value is 0 or >=1, pushing 0 + Sign::Plus | Sign::Zero => U256::ZERO, + // value is <0, pushing -1 + Sign::Minus => U256::MAX, + } + } else { + const ONE: U256 = uint!(1_U256); + // SAFETY: shift count is checked above; it's less than 255. + let shift = usize::try_from(op1).unwrap(); + match value_sign { + Sign::Plus | Sign::Zero => op2.wrapping_shr(shift), + Sign::Minus => two_compl(op2.wrapping_sub(ONE).wrapping_shr(shift).wrapping_add(ONE)), + } + }; +} + +#[cfg(test)] +mod tests { + use crate::instructions::bitwise::{sar, shl, shr}; + use crate::{Contract, DummyHost, Interpreter}; + use revm_primitives::{uint, Env, LatestSpec, U256}; + + #[test] + fn test_shift_left() { + let mut host = DummyHost::new(Env::default()); + let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false); + + struct TestCase { + value: U256, + shift: U256, + expected: U256, + } + + uint! { + let test_cases = [ + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + shift: 0x00_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + }, + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + shift: 0x01_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000002_U256, + }, + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + shift: 0xff_U256, + expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + shift: 0x0100_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + shift: 0x0101_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x00_U256, + expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x01_U256, + expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0xff_U256, + expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x0100_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0x01_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x01_U256, + expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256, + }, + ]; + } + + for test in test_cases { + host.clear(); + push!(interpreter, test.value); + push!(interpreter, test.shift); + shl::(&mut interpreter, &mut host); + pop!(interpreter, res); + assert_eq!(res, test.expected); + } + } + + #[test] + fn test_logical_shift_right() { + let mut host = DummyHost::new(Env::default()); + let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false); + + struct TestCase { + value: U256, + shift: U256, + expected: U256, + } + + uint! { + let test_cases = [ + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + shift: 0x00_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + }, + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + shift: 0x01_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0x01_U256, + expected: 0x4000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0xff_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + }, + TestCase { + value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0x0100_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0x0101_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x00_U256, + expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x01_U256, + expected: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0xff_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x0100_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0x01_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + ]; + } + + for test in test_cases { + host.clear(); + push!(interpreter, test.value); + push!(interpreter, test.shift); + shr::(&mut interpreter, &mut host); + pop!(interpreter, res); + assert_eq!(res, test.expected); + } + } + + #[test] + fn test_arithmetic_shift_right() { + let mut host = DummyHost::new(Env::default()); + let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false); + + struct TestCase { + value: U256, + shift: U256, + expected: U256, + } + + uint! { + let test_cases = [ + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + shift: 0x00_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + }, + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + shift: 0x01_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0x01_U256, + expected: 0xc000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0xff_U256, + expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0x0100_U256, + expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0x0101_U256, + expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x00_U256, + expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x01_U256, + expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0xff_U256, + expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x0100_U256, + expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + }, + TestCase { + value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0x01_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256, + shift: 0xfe_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + }, + TestCase { + value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0xf8_U256, + expected: 0x000000000000000000000000000000000000000000000000000000000000007f_U256, + }, + TestCase { + value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0xfe_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256, + }, + TestCase { + value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0xff_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + TestCase { + value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, + shift: 0x0100_U256, + expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256, + }, + ]; + } + + for test in test_cases { + host.clear(); + push!(interpreter, test.value); + push!(interpreter, test.shift); + sar::(&mut interpreter, &mut host); + pop!(interpreter, res); + assert_eq!(res, test.expected); + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/contract.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/contract.md new file mode 100644 index 00000000..ed01ae1f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/contract.md @@ -0,0 +1,644 @@ +# ๐Ÿฆ€ contract.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/contract.rs) + +```rust +mod call_helpers; + +pub use call_helpers::{ + calc_call_gas, get_memory_input_and_out_ranges, resize_memory_and_return_range, +}; +use revm_primitives::{keccak256, BerlinSpec}; + +use crate::{ + analysis::validate_eof, + gas::{self, cost_per_word, BASE, EOF_CREATE_GAS, KECCAK256WORD}, + instructions::utility::read_u16, + interpreter::Interpreter, + primitives::{Address, Bytes, Eof, Spec, SpecId::*, B256, U256}, + CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInput, Host, + InstructionResult, InterpreterAction, InterpreterResult, LoadAccountResult, MAX_INITCODE_SIZE, +}; +use core::{cmp::max, ops::Range}; +use std::boxed::Box; + +/// Resize memory and return memory range if successful. +/// Return `None` if there is not enough gas. And if `len` +/// is zero return `Some(usize::MAX..usize::MAX)`. +pub fn resize_memory( + interpreter: &mut Interpreter, + offset: U256, + len: U256, +) -> Option> { + let len = as_usize_or_fail_ret!(interpreter, len, None); + if len != 0 { + let offset = as_usize_or_fail_ret!(interpreter, offset, None); + resize_memory!(interpreter, offset, len, None); + // range is checked in resize_memory! macro and it is bounded by usize. + Some(offset..offset + len) + } else { + //unrealistic value so we are sure it is not used + Some(usize::MAX..usize::MAX) + } +} + +/// EOF Create instruction +pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, EOF_CREATE_GAS); + let initcontainer_index = unsafe { *interpreter.instruction_pointer }; + pop!(interpreter, value, salt, data_offset, data_size); + + let sub_container = interpreter + .eof() + .expect("EOF is set") + .body + .container_section + .get(initcontainer_index as usize) + .cloned() + .expect("EOF is checked"); + + // resize memory and get return range. + let Some(return_range) = resize_memory(interpreter, data_offset, data_size) else { + return; + }; + + let eof = Eof::decode(sub_container.clone()).expect("Subcontainer is verified"); + + if !eof.body.is_data_filled { + // should be always false as it is verified by eof verification. + panic!("Panic if data section is not full"); + } + + // deduct gas for hash that is needed to calculate address. + gas_or_fail!( + interpreter, + cost_per_word(sub_container.len() as u64, KECCAK256WORD) + ); + + let created_address = interpreter + .contract + .caller + .create2(salt.to_be_bytes(), keccak256(sub_container)); + + // Send container for execution container is preverified. + interpreter.next_action = InterpreterAction::EOFCreate { + inputs: Box::new(EOFCreateInput::new( + interpreter.contract.target_address, + created_address, + value, + eof, + interpreter.gas().remaining(), + return_range, + )), + }; + + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) }; +} + +pub fn txcreate(interpreter: &mut Interpreter, host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, EOF_CREATE_GAS); + pop!( + interpreter, + tx_initcode_hash, + value, + salt, + data_offset, + data_size + ); + let tx_initcode_hash = B256::from(tx_initcode_hash); + + // resize memory and get return range. + let Some(return_range) = resize_memory(interpreter, data_offset, data_size) else { + return; + }; + + // fetch initcode, if not found push ZERO. + let Some(initcode) = host + .env() + .tx + .eof_initcodes_hashed + .get(&tx_initcode_hash) + .cloned() + else { + push!(interpreter, U256::ZERO); + return; + }; + + // deduct gas for validation + gas_or_fail!(interpreter, cost_per_word(initcode.len() as u64, BASE)); + + // deduct gas for hash. TODO check order of actions. + gas_or_fail!( + interpreter, + cost_per_word(initcode.len() as u64, KECCAK256WORD) + ); + + let Ok(eof) = Eof::decode(initcode.clone()) else { + push!(interpreter, U256::ZERO); + return; + }; + + // Data section should be full, push zero to stack and return if not. + if !eof.body.is_data_filled { + push!(interpreter, U256::ZERO); + return; + } + + // Validate initcode + if validate_eof(&eof).is_err() { + push!(interpreter, U256::ZERO); + return; + } + + // Create new address. Gas for it is already deducted. + let created_address = interpreter + .contract + .caller + .create2(salt.to_be_bytes(), tx_initcode_hash); + + let gas_limit = interpreter.gas().remaining(); + // spend all gas. It will be reimbursed after frame returns. + gas!(interpreter, gas_limit); + + interpreter.next_action = InterpreterAction::EOFCreate { + inputs: Box::new(EOFCreateInput::new( + interpreter.contract.target_address, + created_address, + value, + eof, + gas_limit, + return_range, + )), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; +} + +pub fn return_contract(interpreter: &mut Interpreter, _host: &mut H) { + require_init_eof!(interpreter); + let deploy_container_index = unsafe { read_u16(interpreter.instruction_pointer) }; + pop!(interpreter, aux_data_offset, aux_data_size); + let aux_data_size = as_usize_or_fail!(interpreter, aux_data_size); + // important: offset must be ignored if len is zeros + let container = interpreter + .eof() + .expect("EOF is set") + .body + .container_section + .get(deploy_container_index as usize) + .expect("EOF is checked"); + + // convert to EOF so we can check data section size. + let new_eof = Eof::decode(container.clone()).expect("Container is verified"); + + let aux_slice = if aux_data_size != 0 { + let aux_data_offset = as_usize_or_fail!(interpreter, aux_data_offset); + resize_memory!(interpreter, aux_data_offset, aux_data_size); + + interpreter + .shared_memory + .slice(aux_data_offset, aux_data_size) + } else { + &[] + }; + + let new_data_size = new_eof.body.data_section.len() + aux_slice.len(); + if new_data_size > 0xFFFF { + // aux data is too big + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + } + if new_data_size < new_eof.header.data_size as usize { + // aux data is too small + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + } + + // append data bytes + let output = [new_eof.raw(), aux_slice].concat().into(); + + let result = InstructionResult::ReturnContract; + interpreter.instruction_result = result; + interpreter.next_action = crate::InterpreterAction::Return { + result: InterpreterResult { + output, + gas: interpreter.gas, + result, + }, + }; +} + +pub fn extcall_input(interpreter: &mut Interpreter) -> Option { + pop_ret!(interpreter, input_offset, input_size, None); + + let return_memory_offset = + resize_memory_and_return_range(interpreter, input_offset, input_size)?; + + Some(Bytes::copy_from_slice( + interpreter + .shared_memory + .slice_range(return_memory_offset.clone()), + )) +} + +pub fn extcall_gas_calc( + interpreter: &mut Interpreter, + host: &mut H, + target: Address, + transfers_value: bool, +) -> Option { + let Some(load_result) = host.load_account(target) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return None; + }; + + if load_result.is_cold { + gas!(interpreter, gas::COLD_ACCOUNT_ACCESS_COST, None); + } + + // TODO(EOF) is_empty should only be checked on delegatecall + let call_cost = gas::call_cost( + BerlinSpec::SPEC_ID, + transfers_value, + load_result.is_cold, + load_result.is_empty, + ); + gas!(interpreter, call_cost, None); + + // 7. Calculate the gas available to callee as callerโ€™s + // remaining gas reduced by max(ceil(gas/64), MIN_RETAINED_GAS) (MIN_RETAINED_GAS is 5000). + let gas_reduce = max(interpreter.gas.remaining() / 64, 5000); + let gas_limit = interpreter.gas().remaining().saturating_sub(gas_reduce); + + if gas_limit < 2300 { + interpreter.instruction_result = InstructionResult::CallNotAllowedInsideStatic; + // TODO(EOF) error; + // interpreter.instruction_result = InstructionResult::CallGasTooLow; + return None; + } + + // TODO check remaining gas more then N + + gas!(interpreter, gas_limit, None); + Some(gas_limit) +} + +pub fn extcall(interpreter: &mut Interpreter, host: &mut H) { + require_eof!(interpreter); + pop_address!(interpreter, target_address); + + // input call + let Some(input) = extcall_input(interpreter) else { + return; + }; + + pop!(interpreter, value); + let has_transfer = value != U256::ZERO; + + let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, has_transfer) else { + return; + }; + // TODO Check if static and value 0 + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address, + caller: interpreter.contract.target_address, + bytecode_address: target_address, + value: CallValue::Transfer(value), + scheme: CallScheme::Call, + is_static: interpreter.is_static, + is_eof: true, + return_memory_offset: 0..0, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; +} + +pub fn extdcall(interpreter: &mut Interpreter, host: &mut H) { + require_eof!(interpreter); + pop_address!(interpreter, target_address); + + // input call + let Some(input) = extcall_input(interpreter) else { + return; + }; + + let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, false) else { + return; + }; + // TODO Check if static and value 0 + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address, + caller: interpreter.contract.target_address, + bytecode_address: target_address, + value: CallValue::Apparent(interpreter.contract.call_value), + // TODO(EOF) should be EofDelegateCall? + scheme: CallScheme::DelegateCall, + is_static: interpreter.is_static, + is_eof: true, + return_memory_offset: 0..0, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; +} + +pub fn extscall(interpreter: &mut Interpreter, host: &mut H) { + require_eof!(interpreter); + pop_address!(interpreter, target_address); + + // input call + let Some(input) = extcall_input(interpreter) else { + return; + }; + + let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, false) else { + return; + }; + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address, + caller: interpreter.contract.target_address, + bytecode_address: target_address, + value: CallValue::Transfer(U256::ZERO), + scheme: CallScheme::Call, + is_static: interpreter.is_static, + is_eof: true, + return_memory_offset: 0..0, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; +} + +pub fn create( + interpreter: &mut Interpreter, + host: &mut H, +) { + require_non_staticcall!(interpreter); + + // EIP-1014: Skinny CREATE2 + if IS_CREATE2 { + check!(interpreter, PETERSBURG); + } + + pop!(interpreter, value, code_offset, len); + let len = as_usize_or_fail!(interpreter, len); + + let mut code = Bytes::new(); + if len != 0 { + // EIP-3860: Limit and meter initcode + if SPEC::enabled(SHANGHAI) { + // Limit is set as double of max contract bytecode size + let max_initcode_size = host + .env() + .cfg + .limit_contract_code_size + .map(|limit| limit.saturating_mul(2)) + .unwrap_or(MAX_INITCODE_SIZE); + if len > max_initcode_size { + interpreter.instruction_result = InstructionResult::CreateInitCodeSizeLimit; + return; + } + gas!(interpreter, gas::initcode_cost(len as u64)); + } + + let code_offset = as_usize_or_fail!(interpreter, code_offset); + resize_memory!(interpreter, code_offset, len); + code = Bytes::copy_from_slice(interpreter.shared_memory.slice(code_offset, len)); + } + + // EIP-1014: Skinny CREATE2 + let scheme = if IS_CREATE2 { + pop!(interpreter, salt); + // SAFETY: len is reasonable in size as gas for it is already deducted. + gas_or_fail!(interpreter, gas::create2_cost(len.try_into().unwrap())); + CreateScheme::Create2 { salt } + } else { + gas!(interpreter, gas::CREATE); + CreateScheme::Create + }; + + let mut gas_limit = interpreter.gas().remaining(); + + // EIP-150: Gas cost changes for IO-heavy operations + if SPEC::enabled(TANGERINE) { + // take remaining gas and deduce l64 part of it. + gas_limit -= gas_limit / 64 + } + gas!(interpreter, gas_limit); + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Create { + inputs: Box::new(CreateInputs { + caller: interpreter.contract.target_address, + scheme, + value, + init_code: code, + gas_limit, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; +} + +pub fn call(interpreter: &mut Interpreter, host: &mut H) { + pop!(interpreter, local_gas_limit); + pop_address!(interpreter, to); + // max gas limit is not possible in real ethereum situation. + let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); + + pop!(interpreter, value); + let has_transfer = value != U256::ZERO; + if interpreter.is_static && has_transfer { + interpreter.instruction_result = InstructionResult::CallNotAllowedInsideStatic; + return; + } + + let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else { + return; + }; + + let Some(LoadAccountResult { is_cold, is_empty }) = host.load_account(to) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + let Some(mut gas_limit) = calc_call_gas::( + interpreter, + is_cold, + has_transfer, + is_empty, + local_gas_limit, + ) else { + return; + }; + + gas!(interpreter, gas_limit); + + // add call stipend if there is value to be transferred. + if has_transfer { + gas_limit = gas_limit.saturating_add(gas::CALL_STIPEND); + } + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address: to, + caller: interpreter.contract.target_address, + bytecode_address: to, + value: CallValue::Transfer(value), + scheme: CallScheme::Call, + is_static: interpreter.is_static, + is_eof: false, + return_memory_offset, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; +} + +pub fn call_code(interpreter: &mut Interpreter, host: &mut H) { + pop!(interpreter, local_gas_limit); + pop_address!(interpreter, to); + // max gas limit is not possible in real ethereum situation. + let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); + + pop!(interpreter, value); + let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else { + return; + }; + + let Some(LoadAccountResult { is_cold, .. }) = host.load_account(to) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + + let Some(mut gas_limit) = calc_call_gas::( + interpreter, + is_cold, + value != U256::ZERO, + false, + local_gas_limit, + ) else { + return; + }; + + gas!(interpreter, gas_limit); + + // add call stipend if there is value to be transferred. + if value != U256::ZERO { + gas_limit = gas_limit.saturating_add(gas::CALL_STIPEND); + } + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address: interpreter.contract.target_address, + caller: interpreter.contract.target_address, + bytecode_address: to, + value: CallValue::Transfer(value), + scheme: CallScheme::CallCode, + is_static: interpreter.is_static, + is_eof: false, + return_memory_offset, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; +} + +pub fn delegate_call(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, HOMESTEAD); + pop!(interpreter, local_gas_limit); + pop_address!(interpreter, to); + // max gas limit is not possible in real ethereum situation. + let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); + + let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else { + return; + }; + + let Some(LoadAccountResult { is_cold, .. }) = host.load_account(to) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + let Some(gas_limit) = + calc_call_gas::(interpreter, is_cold, false, false, local_gas_limit) + else { + return; + }; + + gas!(interpreter, gas_limit); + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address: interpreter.contract.target_address, + caller: interpreter.contract.caller, + bytecode_address: to, + value: CallValue::Apparent(interpreter.contract.call_value), + scheme: CallScheme::DelegateCall, + is_static: interpreter.is_static, + is_eof: false, + return_memory_offset, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; +} + +pub fn static_call(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, BYZANTIUM); + pop!(interpreter, local_gas_limit); + pop_address!(interpreter, to); + // max gas limit is not possible in real ethereum situation. + let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); + + let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else { + return; + }; + + let Some(LoadAccountResult { is_cold, .. }) = host.load_account(to) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + + let Some(gas_limit) = + calc_call_gas::(interpreter, is_cold, false, false, local_gas_limit) + else { + return; + }; + gas!(interpreter, gas_limit); + + // Call host to interact with target contract + interpreter.next_action = InterpreterAction::Call { + inputs: Box::new(CallInputs { + input, + gas_limit, + target_address: to, + caller: interpreter.contract.target_address, + bytecode_address: to, + value: CallValue::Transfer(U256::ZERO), + scheme: CallScheme::StaticCall, + is_static: true, + is_eof: false, + return_memory_offset, + }), + }; + interpreter.instruction_result = InstructionResult::CallOrCreate; +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/contract/call_helpers.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/contract/call_helpers.md new file mode 100644 index 00000000..0bae7203 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/contract/call_helpers.md @@ -0,0 +1,75 @@ +# ๐Ÿฆ€ call_helpers.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/contract/call_helpers.rs) + +```rust +use revm_primitives::U256; + +use crate::{ + gas, + interpreter::Interpreter, + primitives::{Bytes, Spec, SpecId::*}, + Host, +}; +use core::{cmp::min, ops::Range}; + +#[inline] +pub fn get_memory_input_and_out_ranges( + interpreter: &mut Interpreter, +) -> Option<(Bytes, Range)> { + pop_ret!(interpreter, in_offset, in_len, out_offset, out_len, None); + + let in_range = resize_memory_and_return_range(interpreter, in_offset, in_len)?; + + let mut input = Bytes::new(); + if !in_range.is_empty() { + input = Bytes::copy_from_slice(interpreter.shared_memory.slice_range(in_range)); + } + + let ret_range = resize_memory_and_return_range(interpreter, out_offset, out_len)?; + Some((input, ret_range)) +} + +/// Resize memory and return range of memory. +/// If `len` is 0 dont touch memory and return `usize::MAX` as offset and 0 as length. +#[inline] +pub fn resize_memory_and_return_range( + interpreter: &mut Interpreter, + offset: U256, + len: U256, +) -> Option> { + let len = as_usize_or_fail_ret!(interpreter, len, None); + let offset = if len != 0 { + let offset = as_usize_or_fail_ret!(interpreter, offset, None); + resize_memory!(interpreter, offset, len, None); + offset + } else { + usize::MAX //unrealistic value so we are sure it is not used + }; + Some(offset..offset + len) +} + +#[inline] +pub fn calc_call_gas( + interpreter: &mut Interpreter, + is_cold: bool, + has_transfer: bool, + new_account_accounting: bool, + local_gas_limit: u64, +) -> Option { + let call_cost = gas::call_cost(SPEC::SPEC_ID, has_transfer, is_cold, new_account_accounting); + + gas!(interpreter, call_cost, None); + + // EIP-150: Gas cost changes for IO-heavy operations + let gas_limit = if SPEC::enabled(TANGERINE) { + let gas = interpreter.gas().remaining(); + // take l64 part of gas_limit + min(gas - gas / 64, local_gas_limit) + } else { + local_gas_limit + }; + + Some(gas_limit) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/control.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/control.md new file mode 100644 index 00000000..a73539d5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/control.md @@ -0,0 +1,337 @@ +# ๐Ÿฆ€ control.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/control.rs) + +```rust +use super::utility::{read_i16, read_u16}; +use crate::{ + gas, + primitives::{Bytes, Spec, U256}, + Host, InstructionResult, Interpreter, InterpreterResult, +}; + +pub fn rjump(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::BASE); + let offset = unsafe { read_i16(interpreter.instruction_pointer) } as isize; + // In spec it is +3 but pointer is already incremented in + // `Interpreter::step` so for revm is +2. + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(offset + 2) }; +} + +pub fn rjumpi(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::CONDITION_JUMP_GAS); + pop!(interpreter, condition); + // In spec it is +3 but pointer is already incremented in + // `Interpreter::step` so for revm is +2. + let mut offset = 2; + if !condition.is_zero() { + offset += unsafe { read_i16(interpreter.instruction_pointer) } as isize; + } + + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(offset) }; +} + +pub fn rjumpv(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::CONDITION_JUMP_GAS); + pop!(interpreter, case); + let case = as_isize_saturated!(case); + + let max_index = unsafe { *interpreter.instruction_pointer } as isize; + // for number of items we are adding 1 to max_index, multiply by 2 as each offset is 2 bytes + // and add 1 for max_index itself. Note that revm already incremented the instruction pointer + let mut offset = (max_index + 1) * 2 + 1; + + if case <= max_index { + offset += unsafe { + read_i16( + interpreter + .instruction_pointer + // offset for max_index that is one byte + .offset(1 + case * 2), + ) + } as isize; + } + + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(offset) }; +} + +pub fn jump(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::MID); + pop!(interpreter, target); + jump_inner(interpreter, target); +} + +pub fn jumpi(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::HIGH); + pop!(interpreter, target, cond); + if cond != U256::ZERO { + jump_inner(interpreter, target); + } +} + +#[inline] +fn jump_inner(interpreter: &mut Interpreter, target: U256) { + let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump); + if !interpreter.contract.is_valid_jump(target) { + interpreter.instruction_result = InstructionResult::InvalidJump; + return; + } + // SAFETY: `is_valid_jump` ensures that `dest` is in bounds. + interpreter.instruction_pointer = unsafe { interpreter.bytecode.as_ptr().add(target) }; +} + +pub fn jumpdest_or_nop(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::JUMPDEST); +} + +pub fn callf(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::LOW); + + let idx = unsafe { read_u16(interpreter.instruction_pointer) } as usize; + // TODO Check stack with EOF types. + + if interpreter.function_stack.return_stack_len() == 1024 { + interpreter.instruction_result = InstructionResult::EOFFunctionStackOverflow; + return; + } + + // push current idx and PC to the callf stack. + // PC is incremented by 2 to point to the next instruction after callf. + interpreter + .function_stack + .push(interpreter.program_counter() + 2, idx); + + interpreter.load_eof_code(idx, 0) +} + +pub fn retf(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::RETF_GAS); + + let Some(fframe) = interpreter.function_stack.pop() else { + panic!("Expected function frame") + }; + + interpreter.load_eof_code(fframe.idx, fframe.pc); +} + +pub fn jumpf(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::LOW); + + let idx = unsafe { read_u16(interpreter.instruction_pointer) } as usize; + + // TODO(EOF) do types stack checks + + interpreter.function_stack.set_current_code_idx(idx); + interpreter.load_eof_code(idx, 0) +} + +pub fn pc(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + // - 1 because we have already advanced the instruction pointer in `Interpreter::step` + push!(interpreter, U256::from(interpreter.program_counter() - 1)); +} + +#[inline] +fn return_inner(interpreter: &mut Interpreter, instruction_result: InstructionResult) { + // zero gas cost + // gas!(interpreter, gas::ZERO); + pop!(interpreter, offset, len); + let len = as_usize_or_fail!(interpreter, len); + // important: offset must be ignored if len is zeros + let mut output = Bytes::default(); + if len != 0 { + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, len); + + output = interpreter.shared_memory.slice(offset, len).to_vec().into() + } + interpreter.instruction_result = instruction_result; + interpreter.next_action = crate::InterpreterAction::Return { + result: InterpreterResult { + output, + gas: interpreter.gas, + result: instruction_result, + }, + }; +} + +pub fn ret(interpreter: &mut Interpreter, _host: &mut H) { + return_inner(interpreter, InstructionResult::Return); +} + +/// EIP-140: REVERT instruction +pub fn revert(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, BYZANTIUM); + return_inner(interpreter, InstructionResult::Revert); +} + +/// Stop opcode. This opcode halts the execution. +pub fn stop(interpreter: &mut Interpreter, _host: &mut H) { + interpreter.instruction_result = InstructionResult::Stop; +} + +/// Invalid opcode. This opcode halts the execution. +pub fn invalid(interpreter: &mut Interpreter, _host: &mut H) { + interpreter.instruction_result = InstructionResult::InvalidFEOpcode; +} + +/// Unknown opcode. This opcode halts the execution. +pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { + interpreter.instruction_result = InstructionResult::OpcodeNotFound; +} + +#[cfg(test)] +mod test { + use revm_primitives::{bytes, Bytecode, Eof, PragueSpec}; + + use super::*; + use crate::{ + opcode::{make_instruction_table, CALLF, JUMPF, NOP, RETF, RJUMP, RJUMPI, RJUMPV, STOP}, + DummyHost, FunctionReturnFrame, Gas, Interpreter, + }; + + #[test] + fn rjump() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ + RJUMP, 0x00, 0x02, STOP, STOP, + ]))); + interp.is_eof = true; + interp.gas = Gas::new(10000); + + interp.step(&table, &mut host); + assert_eq!(interp.program_counter(), 5); + } + + #[test] + fn rjumpi() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ + RJUMPI, 0x00, 0x03, RJUMPI, 0x00, 0x01, STOP, STOP, + ]))); + interp.is_eof = true; + interp.stack.push(U256::from(1)).unwrap(); + interp.stack.push(U256::from(0)).unwrap(); + interp.gas = Gas::new(10000); + + // dont jump + interp.step(&table, &mut host); + assert_eq!(interp.program_counter(), 3); + // jumps to last opcode + interp.step(&table, &mut host); + assert_eq!(interp.program_counter(), 7); + } + + #[test] + fn rjumpv() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ + RJUMPV, + 0x01, // max index, 0 and 1 + 0x00, // first x0001 + 0x01, + 0x00, // second 0x002 + 0x02, + NOP, + NOP, + NOP, + RJUMP, + 0xFF, + (-12i8) as u8, + STOP, + ]))); + interp.is_eof = true; + interp.gas = Gas::new(1000); + + // more then max_index + interp.stack.push(U256::from(10)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.program_counter(), 6); + + // cleanup + interp.step(&table, &mut host); + interp.step(&table, &mut host); + interp.step(&table, &mut host); + interp.step(&table, &mut host); + assert_eq!(interp.program_counter(), 0); + + // jump to first index of vtable + interp.stack.push(U256::from(0)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.program_counter(), 7); + + // cleanup + interp.step(&table, &mut host); + interp.step(&table, &mut host); + interp.step(&table, &mut host); + assert_eq!(interp.program_counter(), 0); + + // jump to second index of vtable + interp.stack.push(U256::from(1)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.program_counter(), 8); + } + + fn dummy_eof() -> Eof { + let bytes = bytes!("ef000101000402000100010400000000800000fe"); + Eof::decode(bytes).unwrap() + } + + #[test] + fn callf_retf_jumpf() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + let mut eof = dummy_eof(); + + eof.body.code_section.clear(); + eof.header.code_sizes.clear(); + + let bytes1 = Bytes::from([CALLF, 0x00, 0x01, JUMPF, 0x00, 0x01]); + eof.header.code_sizes.push(bytes1.len() as u16); + eof.body.code_section.push(bytes1.clone()); + let bytes2 = Bytes::from([STOP, RETF]); + eof.header.code_sizes.push(bytes2.len() as u16); + eof.body.code_section.push(bytes2.clone()); + + let mut interp = Interpreter::new_bytecode(Bytecode::Eof(eof)); + interp.gas = Gas::new(10000); + + assert_eq!(interp.function_stack.current_code_idx, 0); + assert!(interp.function_stack.return_stack.is_empty()); + + // CALLF + interp.step(&table, &mut host); + + assert_eq!(interp.function_stack.current_code_idx, 1); + assert_eq!( + interp.function_stack.return_stack[0], + FunctionReturnFrame::new(0, 3) + ); + assert_eq!(interp.instruction_pointer, bytes2.as_ptr()); + + // STOP + interp.step(&table, &mut host); + // RETF + interp.step(&table, &mut host); + + assert_eq!(interp.function_stack.current_code_idx, 0); + assert_eq!(interp.function_stack.return_stack, Vec::new()); + assert_eq!(interp.program_counter(), 3); + + // JUMPF + interp.step(&table, &mut host); + assert_eq!(interp.function_stack.current_code_idx, 1); + assert_eq!(interp.function_stack.return_stack, Vec::new()); + assert_eq!(interp.instruction_pointer, bytes2.as_ptr()); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/data.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/data.md new file mode 100644 index 00000000..2b8e5837 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/data.md @@ -0,0 +1,220 @@ +# ๐Ÿฆ€ data.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/data.rs) + +```rust +use crate::{ + gas::{BASE, DATA_LOAD_GAS, VERYLOW}, + instructions::utility::read_u16, + interpreter::Interpreter, + primitives::U256, + Host, +}; + +pub fn data_load(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, DATA_LOAD_GAS); + pop_top!(interpreter, offset); + + let offset_usize = as_usize_saturated!(offset); + + let slice = interpreter + .contract + .bytecode + .eof() + .expect("eof") + .data_slice(offset_usize, 32); + + let mut word = [0u8; 32]; + word[..slice.len()].copy_from_slice(slice); + + *offset = U256::from_be_bytes(word); +} + +pub fn data_loadn(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, VERYLOW); + let offset = unsafe { read_u16(interpreter.instruction_pointer) } as usize; + + let slice = interpreter + .contract + .bytecode + .eof() + .expect("eof") + .data_slice(offset, 32); + + let mut word = [0u8; 32]; + word[..slice.len()].copy_from_slice(slice); + + push_b256!(interpreter, word.into()); + + // add +2 to the instruction pointer to skip the offset + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(2) }; +} + +pub fn data_size(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, BASE); + let data_size = interpreter.eof().expect("eof").header.data_size; + + push!(interpreter, U256::from(data_size)); +} + +pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, VERYLOW); + pop!(interpreter, mem_offset, offset, size); + + // sizes more than u64::MAX will spend all the gas in memmory resize. + let size = as_usize_or_fail!(interpreter, size); + // size of zero should not change the memory + if size == 0 { + return; + } + // fail if mem offset is big as it will spend all the gas + let mem_offset = as_usize_or_fail!(interpreter, mem_offset); + resize_memory!(interpreter, mem_offset, size); + + let offset = as_usize_saturated!(offset); + let data = interpreter.contract.bytecode.eof().expect("EOF").data(); + + // set data from the eof to the shared memory. Padd it with zeros. + interpreter + .shared_memory + .set_data(mem_offset, offset, size, data); +} + +#[cfg(test)] +mod test { + use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, PragueSpec}; + + use super::*; + use crate::{ + opcode::{make_instruction_table, DATACOPY, DATALOAD, DATALOADN, DATASIZE}, + DummyHost, Gas, Interpreter, + }; + + fn dummy_eof(code_bytes: Bytes) -> Bytecode { + let bytes = bytes!("ef000101000402000100010400000000800000fe"); + let mut eof = Eof::decode(bytes).unwrap(); + + eof.body.data_section = + bytes!("000000000000000000000000000000000000000000000000000000000000000102030405"); + eof.header.data_size = eof.body.data_section.len() as u16; + + eof.header.code_sizes[0] = code_bytes.len() as u16; + eof.body.code_section[0] = code_bytes; + Bytecode::Eof(eof) + } + + #[test] + fn dataload_dataloadn() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + let eof = dummy_eof(Bytes::from([ + DATALOAD, DATALOADN, 0x00, 0x00, DATALOAD, DATALOADN, 0x00, 35, DATALOAD, DATALOADN, + 0x00, 36, DATASIZE, + ])); + + let mut interp = Interpreter::new_bytecode(eof); + interp.gas = Gas::new(10000); + + // DATALOAD + interp.stack.push(U256::from(0)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.stack.data(), &vec![U256::from(0x01)]); + interp.stack.pop().unwrap(); + + // DATALOADN + interp.step(&table, &mut host); + assert_eq!(interp.stack.data(), &vec![U256::from(0x01)]); + interp.stack.pop().unwrap(); + + // DATALOAD (padding) + interp.stack.push(U256::from(35)).unwrap(); + interp.step(&table, &mut host); + assert_eq!( + interp.stack.data(), + &vec![b256!("0500000000000000000000000000000000000000000000000000000000000000").into()] + ); + interp.stack.pop().unwrap(); + + // DATALOADN (padding) + interp.step(&table, &mut host); + assert_eq!( + interp.stack.data(), + &vec![b256!("0500000000000000000000000000000000000000000000000000000000000000").into()] + ); + interp.stack.pop().unwrap(); + + // DATALOAD (out of bounds) + interp.stack.push(U256::from(36)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.stack.data(), &vec![U256::ZERO]); + interp.stack.pop().unwrap(); + + // DATALOADN (out of bounds) + interp.step(&table, &mut host); + assert_eq!(interp.stack.data(), &vec![U256::ZERO]); + interp.stack.pop().unwrap(); + + // DATA SIZE + interp.step(&table, &mut host); + assert_eq!(interp.stack.data(), &vec![U256::from(36)]); + } + + #[test] + fn data_copy() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + let eof = dummy_eof(Bytes::from([DATACOPY, DATACOPY, DATACOPY, DATACOPY])); + + let mut interp = Interpreter::new_bytecode(eof); + interp.gas = Gas::new(10000); + + // Data copy + // size, offset mem_offset, + interp.stack.push(U256::from(32)).unwrap(); + interp.stack.push(U256::from(0)).unwrap(); + interp.stack.push(U256::from(0)).unwrap(); + interp.step(&table, &mut host); + assert_eq!( + interp.shared_memory.context_memory(), + &bytes!("0000000000000000000000000000000000000000000000000000000000000001") + ); + + // Data copy (Padding) + // size, offset mem_offset, + interp.stack.push(U256::from(2)).unwrap(); + interp.stack.push(U256::from(35)).unwrap(); + interp.stack.push(U256::from(1)).unwrap(); + interp.step(&table, &mut host); + assert_eq!( + interp.shared_memory.context_memory(), + &bytes!("0005000000000000000000000000000000000000000000000000000000000001") + ); + + // Data copy (Out of bounds) + // size, offset mem_offset, + interp.stack.push(U256::from(2)).unwrap(); + interp.stack.push(U256::from(37)).unwrap(); + interp.stack.push(U256::from(1)).unwrap(); + interp.step(&table, &mut host); + assert_eq!( + interp.shared_memory.context_memory(), + &bytes!("0000000000000000000000000000000000000000000000000000000000000001") + ); + + // Data copy (Size == 0) + // mem_offset, offset, size + interp.stack.push(U256::from(0)).unwrap(); + interp.stack.push(U256::from(37)).unwrap(); + interp.stack.push(U256::from(1)).unwrap(); + interp.step(&table, &mut host); + assert_eq!( + interp.shared_memory.context_memory(), + &bytes!("0000000000000000000000000000000000000000000000000000000000000001") + ); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host.md new file mode 100644 index 00000000..e7a4fa36 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host.md @@ -0,0 +1,257 @@ +# ๐Ÿฆ€ host.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/host.rs) + +```rust +use crate::{ + gas::{self, warm_cold_cost}, + interpreter::Interpreter, + primitives::{Bytes, Log, LogData, Spec, SpecId::*, B256, U256}, + Host, InstructionResult, SStoreResult, +}; +use core::cmp::min; +use revm_primitives::{BLOCKHASH_SERVE_WINDOW, BLOCKHASH_STORAGE_ADDRESS, BLOCK_HASH_HISTORY}; +use std::vec::Vec; + +pub fn balance(interpreter: &mut Interpreter, host: &mut H) { + pop_address!(interpreter, address); + let Some((balance, is_cold)) = host.balance(address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + gas!( + interpreter, + if SPEC::enabled(BERLIN) { + warm_cold_cost(is_cold) + } else if SPEC::enabled(ISTANBUL) { + // EIP-1884: Repricing for trie-size-dependent opcodes + 700 + } else if SPEC::enabled(TANGERINE) { + 400 + } else { + 20 + } + ); + push!(interpreter, balance); +} + +/// EIP-1884: Repricing for trie-size-dependent opcodes +pub fn selfbalance(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, ISTANBUL); + gas!(interpreter, gas::LOW); + let Some((balance, _)) = host.balance(interpreter.contract.target_address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + push!(interpreter, balance); +} + +pub fn extcodesize(interpreter: &mut Interpreter, host: &mut H) { + pop_address!(interpreter, address); + let Some((code, is_cold)) = host.code(address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + if SPEC::enabled(BERLIN) { + gas!(interpreter, warm_cold_cost(is_cold)); + } else if SPEC::enabled(TANGERINE) { + gas!(interpreter, 700); + } else { + gas!(interpreter, 20); + } + + push!(interpreter, U256::from(code.len())); +} + +/// EIP-1052: EXTCODEHASH opcode +pub fn extcodehash(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CONSTANTINOPLE); + pop_address!(interpreter, address); + let Some((code_hash, is_cold)) = host.code_hash(address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + if SPEC::enabled(BERLIN) { + gas!(interpreter, warm_cold_cost(is_cold)); + } else if SPEC::enabled(ISTANBUL) { + gas!(interpreter, 700); + } else { + gas!(interpreter, 400); + } + push_b256!(interpreter, code_hash); +} + +pub fn extcodecopy(interpreter: &mut Interpreter, host: &mut H) { + pop_address!(interpreter, address); + pop!(interpreter, memory_offset, code_offset, len_u256); + + let Some((code, is_cold)) = host.code(address) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + + let len = as_usize_or_fail!(interpreter, len_u256); + gas_or_fail!( + interpreter, + gas::extcodecopy_cost(SPEC::SPEC_ID, len as u64, is_cold) + ); + if len == 0 { + return; + } + let memory_offset = as_usize_or_fail!(interpreter, memory_offset); + let code_offset = min(as_usize_saturated!(code_offset), code.len()); + resize_memory!(interpreter, memory_offset, len); + + // Note: this can't panic because we resized memory to fit. + interpreter + .shared_memory + .set_data(memory_offset, code_offset, len, &code.original_bytes()); +} + +pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BLOCKHASH); + pop_top!(interpreter, number); + + let block_number = host.env().block.number; + + match block_number.checked_sub(*number) { + Some(diff) if !diff.is_zero() => { + let diff = as_usize_saturated!(diff); + + // blockhash should push zero if number is same as current block number. + if SPEC::enabled(PRAGUE) && diff <= BLOCKHASH_SERVE_WINDOW { + let value = sload!( + interpreter, + host, + BLOCKHASH_STORAGE_ADDRESS, + number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)) + ); + *number = value; + return; + } else if diff <= BLOCK_HASH_HISTORY { + let Some(hash) = host.block_hash(*number) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + *number = U256::from_be_bytes(hash.0); + return; + } + } + _ => { + // If blockhash is requested for the current block, the hash should be 0, so we fall + // through. + } + } + + *number = U256::ZERO; +} + +pub fn sload(interpreter: &mut Interpreter, host: &mut H) { + pop_top!(interpreter, index); + let value = sload!( + interpreter, + host, + interpreter.contract.target_address, + *index + ); + *index = value; +} + +pub fn sstore(interpreter: &mut Interpreter, host: &mut H) { + require_non_staticcall!(interpreter); + + pop!(interpreter, index, value); + let Some(SStoreResult { + original_value: original, + present_value: old, + new_value: new, + is_cold, + }) = host.sstore(interpreter.contract.target_address, index, value) + else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + gas_or_fail!(interpreter, { + let remaining_gas = interpreter.gas.remaining(); + gas::sstore_cost(SPEC::SPEC_ID, original, old, new, remaining_gas, is_cold) + }); + refund!( + interpreter, + gas::sstore_refund(SPEC::SPEC_ID, original, old, new) + ); +} + +/// EIP-1153: Transient storage opcodes +/// Store value to transient storage +pub fn tstore(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CANCUN); + require_non_staticcall!(interpreter); + gas!(interpreter, gas::WARM_STORAGE_READ_COST); + + pop!(interpreter, index, value); + + host.tstore(interpreter.contract.target_address, index, value); +} + +/// EIP-1153: Transient storage opcodes +/// Load value from transient storage +pub fn tload(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CANCUN); + gas!(interpreter, gas::WARM_STORAGE_READ_COST); + + pop_top!(interpreter, index); + + *index = host.tload(interpreter.contract.target_address, *index); +} + +pub fn log(interpreter: &mut Interpreter, host: &mut H) { + require_non_staticcall!(interpreter); + + pop!(interpreter, offset, len); + let len = as_usize_or_fail!(interpreter, len); + gas_or_fail!(interpreter, gas::log_cost(N as u8, len as u64)); + let data = if len == 0 { + Bytes::new() + } else { + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, len); + Bytes::copy_from_slice(interpreter.shared_memory.slice(offset, len)) + }; + + if interpreter.stack.len() < N { + interpreter.instruction_result = InstructionResult::StackUnderflow; + return; + } + + let mut topics = Vec::with_capacity(N); + for _ in 0..N { + // SAFETY: stack bounds already checked few lines above + topics.push(B256::from(unsafe { interpreter.stack.pop_unsafe() })); + } + + let log = Log { + address: interpreter.contract.target_address, + data: LogData::new(topics, data).expect("LogData should have <=4 topics"), + }; + + host.log(log); +} + +pub fn selfdestruct(interpreter: &mut Interpreter, host: &mut H) { + require_non_staticcall!(interpreter); + pop_address!(interpreter, target); + + let Some(res) = host.selfdestruct(interpreter.contract.target_address, target) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + + // EIP-3529: Reduction in refunds + if !SPEC::enabled(LONDON) && !res.previously_destroyed { + refund!(interpreter, gas::SELFDESTRUCT) + } + gas!(interpreter, gas::selfdestruct_cost(SPEC::SPEC_ID, res)); + + interpreter.instruction_result = InstructionResult::SelfDestruct; +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host/call_helpers.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host/call_helpers.md new file mode 100644 index 00000000..8c1e9f4f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host/call_helpers.md @@ -0,0 +1,79 @@ +# ๐Ÿฆ€ call_helpers.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/host/call_helpers.rs) + +```rust +use crate::{ + gas::{self}, + interpreter::Interpreter, + primitives::{Address, Bytes, Spec, SpecId::*}, + Host, InstructionResult, +}; +use core::{cmp::min, ops::Range}; + +#[inline] +pub fn get_memory_input_and_out_ranges( + interpreter: &mut Interpreter, +) -> Option<(Bytes, Range)> { + pop_ret!(interpreter, in_offset, in_len, out_offset, out_len, None); + + let in_len = as_usize_or_fail_ret!(interpreter, in_len, None); + let input = if in_len != 0 { + let in_offset = as_usize_or_fail_ret!(interpreter, in_offset, None); + resize_memory!(interpreter, in_offset, in_len, None); + Bytes::copy_from_slice(interpreter.shared_memory.slice(in_offset, in_len)) + } else { + Bytes::new() + }; + + let out_len = as_usize_or_fail_ret!(interpreter, out_len, None); + let out_offset = if out_len != 0 { + let out_offset = as_usize_or_fail_ret!(interpreter, out_offset, None); + resize_memory!(interpreter, out_offset, out_len, None); + out_offset + } else { + usize::MAX //unrealistic value so we are sure it is not used + }; + + Some((input, out_offset..out_offset + out_len)) +} + +#[inline] +pub fn calc_call_gas( + interpreter: &mut Interpreter, + host: &mut H, + to: Address, + has_transfer: bool, + local_gas_limit: u64, + is_call_or_callcode: bool, + is_call_or_staticcall: bool, +) -> Option { + let Some((is_cold, exist)) = host.load_account(to) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return None; + }; + let is_new = !exist; + + let call_cost = gas::call_cost( + SPEC::SPEC_ID, + has_transfer, + is_new, + is_cold, + is_call_or_callcode, + is_call_or_staticcall, + ); + + gas!(interpreter, call_cost, None); + + // EIP-150: Gas cost changes for IO-heavy operations + let gas_limit = if SPEC::enabled(TANGERINE) { + let gas = interpreter.gas().remaining(); + // take l64 part of gas_limit + min(gas - gas / 64, local_gas_limit) + } else { + local_gas_limit + }; + + Some(gas_limit) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host_env.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host_env.md new file mode 100644 index 00000000..f62c4dc3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/host_env.md @@ -0,0 +1,86 @@ +# ๐Ÿฆ€ host_env.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/host_env.rs) + +```rust +use crate::{ + gas, + primitives::{Spec, SpecId::*, U256}, + Host, Interpreter, +}; + +/// EIP-1344: ChainID opcode +pub fn chainid(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, ISTANBUL); + gas!(interpreter, gas::BASE); + push!(interpreter, U256::from(host.env().cfg.chain_id)); +} + +pub fn coinbase(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push_b256!(interpreter, host.env().block.coinbase.into_word()); +} + +pub fn timestamp(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().block.timestamp); +} + +pub fn block_number(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().block.number); +} + +pub fn difficulty(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + if SPEC::enabled(MERGE) { + push_b256!(interpreter, host.env().block.prevrandao.unwrap()); + } else { + push!(interpreter, host.env().block.difficulty); + } +} + +pub fn gaslimit(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().block.gas_limit); +} + +pub fn gasprice(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().effective_gas_price()); +} + +/// EIP-3198: BASEFEE opcode +pub fn basefee(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, LONDON); + gas!(interpreter, gas::BASE); + push!(interpreter, host.env().block.basefee); +} + +pub fn origin(interpreter: &mut Interpreter, host: &mut H) { + gas!(interpreter, gas::BASE); + push_b256!(interpreter, host.env().tx.caller.into_word()); +} + +// EIP-4844: Shard Blob Transactions +pub fn blob_hash(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CANCUN); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, index); + let i = as_usize_saturated!(index); + *index = match host.env().tx.blob_hashes.get(i) { + Some(hash) => U256::from_be_bytes(hash.0), + None => U256::ZERO, + }; +} + +/// EIP-7516: BLOBBASEFEE opcode +pub fn blob_basefee(interpreter: &mut Interpreter, host: &mut H) { + check!(interpreter, CANCUN); + gas!(interpreter, gas::BASE); + push!( + interpreter, + U256::from(host.env().block.get_blob_gasprice().unwrap_or_default()) + ); +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/i256.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/i256.md new file mode 100644 index 00000000..ad173b26 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/i256.md @@ -0,0 +1,248 @@ +# ๐Ÿฆ€ i256.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/i256.rs) + +```rust +use crate::primitives::U256; +use core::cmp::Ordering; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(i8)] +pub enum Sign { + // same as `cmp::Ordering` + Minus = -1, + Zero = 0, + #[allow(dead_code)] // "constructed" with `mem::transmute` in `i256_sign` below + Plus = 1, +} + +pub const MAX_POSITIVE_VALUE: U256 = U256::from_limbs([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0x7fffffffffffffff, +]); + +pub const MIN_NEGATIVE_VALUE: U256 = U256::from_limbs([ + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x8000000000000000, +]); + +const FLIPH_BITMASK_U64: u64 = 0x7FFFFFFFFFFFFFFF; + +#[inline] +pub fn i256_sign(val: &U256) -> Sign { + if val.bit(U256::BITS - 1) { + Sign::Minus + } else { + // SAFETY: false == 0 == Zero, true == 1 == Plus + unsafe { core::mem::transmute(*val != U256::ZERO) } + } +} + +#[inline] +pub fn i256_sign_compl(val: &mut U256) -> Sign { + let sign = i256_sign(val); + if sign == Sign::Minus { + two_compl_mut(val); + } + sign +} + +#[inline] +fn u256_remove_sign(val: &mut U256) { + // SAFETY: U256 does not have any padding bytes + unsafe { + val.as_limbs_mut()[3] &= FLIPH_BITMASK_U64; + } +} + +#[inline] +pub fn two_compl_mut(op: &mut U256) { + *op = two_compl(*op); +} + +#[inline] +pub fn two_compl(op: U256) -> U256 { + op.wrapping_neg() +} + +#[inline] +pub fn i256_cmp(first: &U256, second: &U256) -> Ordering { + let first_sign = i256_sign(first); + let second_sign = i256_sign(second); + match first_sign.cmp(&second_sign) { + // note: adding `if first_sign != Sign::Zero` to short circuit zero comparisons performs + // slower on average, as of #582 + Ordering::Equal => first.cmp(second), + o => o, + } +} + +#[inline] +pub fn i256_div(mut first: U256, mut second: U256) -> U256 { + let second_sign = i256_sign_compl(&mut second); + if second_sign == Sign::Zero { + return U256::ZERO; + } + + let first_sign = i256_sign_compl(&mut first); + if first == MIN_NEGATIVE_VALUE && second == U256::from(1) { + return two_compl(MIN_NEGATIVE_VALUE); + } + + // necessary overflow checks are done above, perform the division + let mut d = first / second; + + // set sign bit to zero + u256_remove_sign(&mut d); + + // two's complement only if the signs are different + // note: this condition has better codegen than an exhaustive match, as of #582 + if (first_sign == Sign::Minus && second_sign != Sign::Minus) + || (second_sign == Sign::Minus && first_sign != Sign::Minus) + { + two_compl(d) + } else { + d + } +} + +#[inline] +pub fn i256_mod(mut first: U256, mut second: U256) -> U256 { + let first_sign = i256_sign_compl(&mut first); + if first_sign == Sign::Zero { + return U256::ZERO; + } + + let second_sign = i256_sign_compl(&mut second); + if second_sign == Sign::Zero { + return U256::ZERO; + } + + let mut r = first % second; + + // set sign bit to zero + u256_remove_sign(&mut r); + + if first_sign == Sign::Minus { + two_compl(r) + } else { + r + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::primitives::uint; + use core::num::Wrapping; + + #[test] + fn div_i256() { + // Sanity checks based on i8. Notice that we need to use `Wrapping` here because + // Rust will prevent the overflow by default whereas the EVM does not. + assert_eq!(Wrapping(i8::MIN) / Wrapping(-1), Wrapping(i8::MIN)); + assert_eq!(i8::MAX / -1, -i8::MAX); + + uint! { + assert_eq!(i256_div(MIN_NEGATIVE_VALUE, -1_U256), MIN_NEGATIVE_VALUE); + assert_eq!(i256_div(MIN_NEGATIVE_VALUE, 1_U256), MIN_NEGATIVE_VALUE); + assert_eq!(i256_div(MAX_POSITIVE_VALUE, 1_U256), MAX_POSITIVE_VALUE); + assert_eq!(i256_div(MAX_POSITIVE_VALUE, -1_U256), -1_U256 * MAX_POSITIVE_VALUE); + assert_eq!(i256_div(100_U256, -1_U256), -100_U256); + assert_eq!(i256_div(100_U256, 2_U256), 50_U256); + } + } + #[test] + fn test_i256_sign() { + uint! { + assert_eq!(i256_sign(&0_U256), Sign::Zero); + assert_eq!(i256_sign(&1_U256), Sign::Plus); + assert_eq!(i256_sign(&-1_U256), Sign::Minus); + assert_eq!(i256_sign(&MIN_NEGATIVE_VALUE), Sign::Minus); + assert_eq!(i256_sign(&MAX_POSITIVE_VALUE), Sign::Plus); + } + } + + #[test] + fn test_i256_sign_compl() { + uint! { + let mut zero = 0_U256; + let mut positive = 1_U256; + let mut negative = -1_U256; + assert_eq!(i256_sign_compl(&mut zero), Sign::Zero); + assert_eq!(i256_sign_compl(&mut positive), Sign::Plus); + assert_eq!(i256_sign_compl(&mut negative), Sign::Minus); + } + } + + #[test] + fn test_two_compl() { + uint! { + assert_eq!(two_compl(0_U256), 0_U256); + assert_eq!(two_compl(1_U256), -1_U256); + assert_eq!(two_compl(-1_U256), 1_U256); + assert_eq!(two_compl(2_U256), -2_U256); + assert_eq!(two_compl(-2_U256), 2_U256); + + // Two's complement of the min value is itself. + assert_eq!(two_compl(MIN_NEGATIVE_VALUE), MIN_NEGATIVE_VALUE); + } + } + + #[test] + fn test_two_compl_mut() { + uint! { + let mut value = 1_U256; + two_compl_mut(&mut value); + assert_eq!(value, -1_U256); + } + } + + #[test] + fn test_i256_cmp() { + uint! { + assert_eq!(i256_cmp(&1_U256, &2_U256), Ordering::Less); + assert_eq!(i256_cmp(&2_U256, &2_U256), Ordering::Equal); + assert_eq!(i256_cmp(&3_U256, &2_U256), Ordering::Greater); + assert_eq!(i256_cmp(&-1_U256, &-1_U256), Ordering::Equal); + assert_eq!(i256_cmp(&-1_U256, &-2_U256), Ordering::Greater); + assert_eq!(i256_cmp(&-1_U256, &0_U256), Ordering::Less); + assert_eq!(i256_cmp(&-2_U256, &2_U256), Ordering::Less); + } + } + + #[test] + fn test_i256_div() { + uint! { + assert_eq!(i256_div(1_U256, 0_U256), 0_U256); + assert_eq!(i256_div(0_U256, 1_U256), 0_U256); + assert_eq!(i256_div(0_U256, -1_U256), 0_U256); + assert_eq!(i256_div(MIN_NEGATIVE_VALUE, 1_U256), MIN_NEGATIVE_VALUE); + assert_eq!(i256_div(4_U256, 2_U256), 2_U256); + assert_eq!(i256_div(MIN_NEGATIVE_VALUE, MIN_NEGATIVE_VALUE), 1_U256); + assert_eq!(i256_div(2_U256, -1_U256), -2_U256); + assert_eq!(i256_div(-2_U256, -1_U256), 2_U256); + } + } + + #[test] + fn test_i256_mod() { + uint! { + assert_eq!(i256_mod(0_U256, 1_U256), 0_U256); + assert_eq!(i256_mod(1_U256, 0_U256), 0_U256); + assert_eq!(i256_mod(4_U256, 2_U256), 0_U256); + assert_eq!(i256_mod(3_U256, 2_U256), 1_U256); + assert_eq!(i256_mod(MIN_NEGATIVE_VALUE, 1_U256), 0_U256); + assert_eq!(i256_mod(2_U256, 2_U256), 0_U256); + assert_eq!(i256_mod(2_U256, 3_U256), 2_U256); + assert_eq!(i256_mod(-2_U256, 3_U256), -2_U256); + assert_eq!(i256_mod(2_U256, -3_U256), 2_U256); + assert_eq!(i256_mod(-2_U256, -3_U256), -2_U256); + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/macros.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/macros.md new file mode 100644 index 00000000..203167f8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/macros.md @@ -0,0 +1,373 @@ +# ๐Ÿฆ€ macros.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/macros.rs) + +```rust +//! Utility macros to help implementing opcode instruction functions. + +/// Fails the instruction if the current call is static. +#[macro_export] +macro_rules! require_non_staticcall { + ($interp:expr) => { + if $interp.is_static { + $interp.instruction_result = $crate::InstructionResult::StateChangeDuringStaticCall; + return; + } + }; +} + +/// Error if the current call is executing EOF. +#[macro_export] +macro_rules! require_eof { + ($interp:expr) => { + if !$interp.is_eof { + $interp.instruction_result = $crate::InstructionResult::EOFOpcodeDisabledInLegacy; + return; + } + }; +} + +/// Error if not init eof call. +#[macro_export] +macro_rules! require_init_eof { + ($interp:expr) => { + if !$interp.is_eof_init { + $interp.instruction_result = $crate::InstructionResult::ReturnContractInNotInitEOF; + return; + } + }; +} + +/// Check if the `SPEC` is enabled, and fail the instruction if it is not. +#[macro_export] +macro_rules! check { + ($interp:expr, $min:ident) => { + // TODO: Force const-eval on the condition with a `const {}` block once they are stable + if !::enabled($crate::primitives::SpecId::$min) { + $interp.instruction_result = $crate::InstructionResult::NotActivated; + return; + } + }; +} + +/// Performs an `SLOAD` on the target account and storage index. +/// +/// If the slot could not be loaded, or if the gas cost could not be charged, the expanded code +/// sets the instruction result and returns accordingly. +/// +/// # Note +/// +/// This macro charges gas. +/// +/// # Returns +/// +/// Expands to the value of the storage slot. +#[macro_export] +macro_rules! sload { + ($interp:expr, $host:expr, $address:expr, $index:expr) => {{ + let Some((value, is_cold)) = $host.sload($address, $index) else { + $interp.instruction_result = $crate::InstructionResult::FatalExternalError; + return; + }; + $crate::gas!($interp, $crate::gas::sload_cost(SPEC::SPEC_ID, is_cold)); + value + }}; +} + +/// Records a `gas` cost and fails the instruction if it would exceed the available gas. +#[macro_export] +macro_rules! gas { + ($interp:expr, $gas:expr) => { + $crate::gas!($interp, $gas, ()) + }; + ($interp:expr, $gas:expr, $ret:expr) => { + if !$interp.gas.record_cost($gas) { + $interp.instruction_result = $crate::InstructionResult::OutOfGas; + return $ret; + } + }; +} + +/// Records a `gas` refund. +#[macro_export] +macro_rules! refund { + ($interp:expr, $gas:expr) => { + $interp.gas.record_refund($gas) + }; +} + +/// Same as [`gas!`], but with `gas` as an option. +#[macro_export] +macro_rules! gas_or_fail { + ($interp:expr, $gas:expr) => { + match $gas { + Some(gas_used) => $crate::gas!($interp, gas_used), + None => { + $interp.instruction_result = $crate::InstructionResult::OutOfGas; + return; + } + } + }; +} + +/// Resizes the interpreter memory if necessary. Fails the instruction if the memory or gas limit +/// is exceeded. +#[macro_export] +macro_rules! resize_memory { + ($interp:expr, $offset:expr, $len:expr) => { + $crate::resize_memory!($interp, $offset, $len, ()) + }; + ($interp:expr, $offset:expr, $len:expr, $ret:expr) => { + let new_size = $offset.saturating_add($len); + if new_size > $interp.shared_memory.len() { + #[cfg(feature = "memory_limit")] + if $interp.shared_memory.limit_reached(new_size) { + $interp.instruction_result = $crate::InstructionResult::MemoryLimitOOG; + return $ret; + } + + // Note: we can't use `Interpreter` directly here because of potential double-borrows. + if !$crate::interpreter::resize_memory( + &mut $interp.shared_memory, + &mut $interp.gas, + new_size, + ) { + $interp.instruction_result = $crate::InstructionResult::MemoryOOG; + return $ret; + } + } + }; +} + +/// Pops `Address` values from the stack. Fails the instruction if the stack is too small. +#[macro_export] +macro_rules! pop_address { + ($interp:expr, $x1:ident) => { + pop_address_ret!($interp, $x1, ()) + }; + ($interp:expr, $x1:ident, $x2:ident) => { + pop_address_ret!($interp, $x1, $x2, ()) + }; +} + +/// Pop `Address` values from the stack, returns `ret` on stack underflow. +#[macro_export] +macro_rules! pop_address_ret { + ($interp:expr, $x1:ident, $ret:expr) => { + if $interp.stack.len() < 1 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return $ret; + } + // SAFETY: Length is checked above. + let $x1 = $crate::primitives::Address::from_word($crate::primitives::B256::from(unsafe { + $interp.stack.pop_unsafe() + })); + }; + ($interp:expr, $x1:ident, $x2:ident, $ret:expr) => { + if $interp.stack.len() < 2 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return $ret; + } + // SAFETY: Length is checked above. + let $x1 = $crate::primitives::Address::from_word($crate::primitives::B256::from(unsafe { + $interp.stack.pop_unsafe() + })); + let $x2 = $crate::primitives::Address::from_word($crate::primitives::B256::from(unsafe { + $interp.stack.pop_unsafe() + })); + }; +} + +/// Pops `U256` values from the stack. Fails the instruction if the stack is too small. +#[macro_export] +macro_rules! pop { + ($interp:expr, $x1:ident) => { + $crate::pop_ret!($interp, $x1, ()) + }; + ($interp:expr, $x1:ident, $x2:ident) => { + $crate::pop_ret!($interp, $x1, $x2, ()) + }; + ($interp:expr, $x1:ident, $x2:ident, $x3:ident) => { + $crate::pop_ret!($interp, $x1, $x2, $x3, ()) + }; + ($interp:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident) => { + $crate::pop_ret!($interp, $x1, $x2, $x3, $x4, ()) + }; + ($interp:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident, $x5:ident) => { + pop_ret!($interp, $x1, $x2, $x3, $x4, $x5, ()) + }; +} + +/// Pops `U256` values from the stack, and returns `ret`. +/// Fails the instruction if the stack is too small. +#[macro_export] +macro_rules! pop_ret { + ($interp:expr, $x1:ident, $ret:expr) => { + if $interp.stack.len() < 1 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return $ret; + } + // SAFETY: Length is checked above. + let $x1 = unsafe { $interp.stack.pop_unsafe() }; + }; + ($interp:expr, $x1:ident, $x2:ident, $ret:expr) => { + if $interp.stack.len() < 2 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return $ret; + } + // SAFETY: Length is checked above. + let ($x1, $x2) = unsafe { $interp.stack.pop2_unsafe() }; + }; + ($interp:expr, $x1:ident, $x2:ident, $x3:ident, $ret:expr) => { + if $interp.stack.len() < 3 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return $ret; + } + // SAFETY: Length is checked above. + let ($x1, $x2, $x3) = unsafe { $interp.stack.pop3_unsafe() }; + }; + ($interp:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident, $ret:expr) => { + if $interp.stack.len() < 4 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return $ret; + } + // SAFETY: Length is checked above. + let ($x1, $x2, $x3, $x4) = unsafe { $interp.stack.pop4_unsafe() }; + }; + ($interp:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident, $x5:ident, $ret:expr) => { + if $interp.stack.len() < 4 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return $ret; + } + // SAFETY: Length is checked above. + let ($x1, $x2, $x3, $x4, $x5) = unsafe { $interp.stack.pop5_unsafe() }; + }; +} + +/// Pops `U256` values from the stack, and returns a reference to the top of the stack. +/// Fails the instruction if the stack is too small. +#[macro_export] +macro_rules! pop_top { + ($interp:expr, $x1:ident) => { + if $interp.stack.len() < 1 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return; + } + // SAFETY: Length is checked above. + let $x1 = unsafe { $interp.stack.top_unsafe() }; + }; + ($interp:expr, $x1:ident, $x2:ident) => { + if $interp.stack.len() < 2 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return; + } + // SAFETY: Length is checked above. + let ($x1, $x2) = unsafe { $interp.stack.pop_top_unsafe() }; + }; + ($interp:expr, $x1:ident, $x2:ident, $x3:ident) => { + if $interp.stack.len() < 3 { + $interp.instruction_result = $crate::InstructionResult::StackUnderflow; + return; + } + // SAFETY: Length is checked above. + let ($x1, $x2, $x3) = unsafe { $interp.stack.pop2_top_unsafe() }; + }; +} + +/// Pushes `B256` values onto the stack. Fails the instruction if the stack is full. +#[macro_export] +macro_rules! push_b256 { + ($interp:expr, $($x:expr),* $(,)?) => ($( + match $interp.stack.push_b256($x) { + Ok(()) => {}, + Err(e) => { + $interp.instruction_result = e; + return; + }, + } + )*) +} + +/// Pushes a `B256` value onto the stack. Fails the instruction if the stack is full. +#[macro_export] +macro_rules! push { + ($interp:expr, $($x:expr),* $(,)?) => ($( + match $interp.stack.push($x) { + Ok(()) => {}, + Err(e) => { + $interp.instruction_result = e; + return; + } + } + )*) +} + +/// Converts a `U256` value to a `u64`, saturating to `MAX` if the value is too large. +#[macro_export] +macro_rules! as_u64_saturated { + ($v:expr) => {{ + let x: &[u64; 4] = $v.as_limbs(); + if x[1] == 0 && x[2] == 0 && x[3] == 0 { + x[0] + } else { + u64::MAX + } + }}; +} + +/// Converts a `U256` value to a `usize`, saturating to `MAX` if the value is too large. +#[macro_export] +macro_rules! as_usize_saturated { + ($v:expr) => { + usize::try_from($crate::as_u64_saturated!($v)).unwrap_or(usize::MAX) + }; +} + +/// Converts a `U256` value to a `isize`, saturating to `isize::MAX` if the value is too large. +#[macro_export] +macro_rules! as_isize_saturated { + ($v:expr) => { + // `isize_try_from(u64::MAX)`` will fail and return isize::MAX + // this is expected behavior as we are saturating the value. + isize::try_from($crate::as_u64_saturated!($v)).unwrap_or(isize::MAX) + }; +} + +/// Converts a `U256` value to a `usize`, failing the instruction if the value is too large. +#[macro_export] +macro_rules! as_usize_or_fail { + ($interp:expr, $v:expr) => { + $crate::as_usize_or_fail_ret!($interp, $v, ()) + }; + ($interp:expr, $v:expr, $reason:expr) => { + $crate::as_usize_or_fail_ret!($interp, $v, $reason, ()) + }; +} + +/// Converts a `U256` value to a `usize` and returns `ret`, +/// failing the instruction if the value is too large. +#[macro_export] +macro_rules! as_usize_or_fail_ret { + ($interp:expr, $v:expr, $ret:expr) => { + $crate::as_usize_or_fail_ret!( + $interp, + $v, + $crate::InstructionResult::InvalidOperandOOG, + $ret + ) + }; + + ($interp:expr, $v:expr, $reason:expr, $ret:expr) => {{ + let x = $v.as_limbs(); + if x[1] != 0 || x[2] != 0 || x[3] != 0 { + $interp.instruction_result = $reason; + return $ret; + } + let Ok(val) = usize::try_from(x[0]) else { + $interp.instruction_result = $reason; + return $ret; + }; + val + }}; +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/memory.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/memory.md new file mode 100644 index 00000000..6a60e28d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/memory.md @@ -0,0 +1,62 @@ +# ๐Ÿฆ€ memory.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/memory.rs) + +```rust +use crate::{ + gas, + primitives::{Spec, U256}, + Host, Interpreter, +}; +use core::cmp::max; + +pub fn mload(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, top); + let offset = as_usize_or_fail!(interpreter, top); + resize_memory!(interpreter, offset, 32); + *top = interpreter.shared_memory.get_u256(offset); +} + +pub fn mstore(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop!(interpreter, offset, value); + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, 32); + interpreter.shared_memory.set_u256(offset, value); +} + +pub fn mstore8(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop!(interpreter, offset, value); + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, 1); + interpreter.shared_memory.set_byte(offset, value.byte(0)) +} + +pub fn msize(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, U256::from(interpreter.shared_memory.len())); +} + +// EIP-5656: MCOPY - Memory copying instruction +pub fn mcopy(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, CANCUN); + pop!(interpreter, dst, src, len); + + // into usize or fail + let len = as_usize_or_fail!(interpreter, len); + // deduce gas + gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); + if len == 0 { + return; + } + + let dst = as_usize_or_fail!(interpreter, dst); + let src = as_usize_or_fail!(interpreter, src); + // resize memory + resize_memory!(interpreter, max(dst, src), len); + // copy memory in place + interpreter.shared_memory.copy(dst, src, len); +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/stack.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/stack.md new file mode 100644 index 00000000..828e0751 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/stack.md @@ -0,0 +1,165 @@ +# ๐Ÿฆ€ stack.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/stack.rs) + +```rust +use crate::{ + gas, + primitives::{Spec, U256}, + Host, Interpreter, +}; + +pub fn pop(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + if let Err(result) = interpreter.stack.pop() { + interpreter.instruction_result = result; + } +} + +/// EIP-3855: PUSH0 instruction +/// +/// Introduce a new instruction which pushes the constant value 0 onto the stack. +pub fn push0(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, SHANGHAI); + gas!(interpreter, gas::BASE); + if let Err(result) = interpreter.stack.push(U256::ZERO) { + interpreter.instruction_result = result; + } +} + +pub fn push(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + // SAFETY: In analysis we append trailing bytes to the bytecode so that this is safe to do + // without bounds checking. + let ip = interpreter.instruction_pointer; + if let Err(result) = interpreter + .stack + .push_slice(unsafe { core::slice::from_raw_parts(ip, N) }) + { + interpreter.instruction_result = result; + return; + } + interpreter.instruction_pointer = unsafe { ip.add(N) }; +} + +pub fn dup(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + if let Err(result) = interpreter.stack.dup(N) { + interpreter.instruction_result = result; + } +} + +pub fn swap(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + if let Err(result) = interpreter.stack.swap(N) { + interpreter.instruction_result = result; + } +} + +pub fn dupn(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::VERYLOW); + let imm = unsafe { *interpreter.instruction_pointer }; + if let Err(result) = interpreter.stack.dup(imm as usize + 1) { + interpreter.instruction_result = result; + } + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) }; +} + +pub fn swapn(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::VERYLOW); + let imm = unsafe { *interpreter.instruction_pointer }; + if let Err(result) = interpreter.stack.swap(imm as usize + 1) { + interpreter.instruction_result = result; + } + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) }; +} + +pub fn exchange(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::VERYLOW); + let imm = unsafe { *interpreter.instruction_pointer }; + let n = (imm >> 4) + 1; + let m = (imm & 0x0F) + 1; + if let Err(result) = interpreter.stack.exchange(n as usize, m as usize) { + interpreter.instruction_result = result; + } + + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) }; +} + +#[cfg(test)] +mod test { + use super::*; + use crate::{ + opcode::{make_instruction_table, DUPN, EXCHANGE, SWAPN}, + primitives::{Bytecode, Bytes, PragueSpec}, + DummyHost, Gas, InstructionResult, + }; + + #[test] + fn dupn() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ + DUPN, 0x00, DUPN, 0x01, DUPN, 0x02, + ]))); + interp.is_eof = true; + interp.gas = Gas::new(10000); + + interp.stack.push(U256::from(10)).unwrap(); + interp.stack.push(U256::from(20)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.stack.pop(), Ok(U256::from(20))); + interp.step(&table, &mut host); + assert_eq!(interp.stack.pop(), Ok(U256::from(10))); + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::StackUnderflow); + } + + #[test] + fn swapn() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + let mut interp = + Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([SWAPN, 0x00, SWAPN, 0x01]))); + interp.is_eof = true; + interp.gas = Gas::new(10000); + + interp.stack.push(U256::from(10)).unwrap(); + interp.stack.push(U256::from(20)).unwrap(); + interp.stack.push(U256::from(0)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.stack.peek(0), Ok(U256::from(20))); + assert_eq!(interp.stack.peek(1), Ok(U256::from(0))); + interp.step(&table, &mut host); + assert_eq!(interp.stack.peek(0), Ok(U256::from(10))); + assert_eq!(interp.stack.peek(2), Ok(U256::from(20))); + } + + #[test] + fn exchange() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ + EXCHANGE, 0x00, EXCHANGE, 0x11, + ]))); + interp.is_eof = true; + interp.gas = Gas::new(10000); + + interp.stack.push(U256::from(1)).unwrap(); + interp.stack.push(U256::from(5)).unwrap(); + interp.stack.push(U256::from(10)).unwrap(); + interp.stack.push(U256::from(15)).unwrap(); + interp.stack.push(U256::from(0)).unwrap(); + + interp.step(&table, &mut host); + assert_eq!(interp.stack.peek(1), Ok(U256::from(10))); + assert_eq!(interp.stack.peek(2), Ok(U256::from(15))); + interp.step(&table, &mut host); + assert_eq!(interp.stack.peek(2), Ok(U256::from(1))); + assert_eq!(interp.stack.peek(4), Ok(U256::from(15))); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/system.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/system.md new file mode 100644 index 00000000..9f9ee8e2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/system.md @@ -0,0 +1,216 @@ +# ๐Ÿฆ€ system.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/system.rs) + +```rust +use crate::{ + gas, + primitives::{Spec, B256, KECCAK_EMPTY, U256}, + Host, InstructionResult, Interpreter, +}; +use core::ptr; + +pub fn keccak256(interpreter: &mut Interpreter, _host: &mut H) { + pop_top!(interpreter, offset, len_ptr); + let len = as_usize_or_fail!(interpreter, len_ptr); + gas_or_fail!(interpreter, gas::keccak256_cost(len as u64)); + let hash = if len == 0 { + KECCAK_EMPTY + } else { + let from = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, from, len); + crate::primitives::keccak256(interpreter.shared_memory.slice(from, len)) + }; + *len_ptr = hash.into(); +} + +pub fn address(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push_b256!(interpreter, interpreter.contract.target_address.into_word()); +} + +pub fn caller(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push_b256!(interpreter, interpreter.contract.caller.into_word()); +} + +pub fn codesize(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + // Inform the optimizer that the bytecode cannot be EOF to remove a bounds check. + assume!(!interpreter.contract.bytecode.is_eof()); + push!(interpreter, U256::from(interpreter.contract.bytecode.len())); +} + +pub fn codecopy(interpreter: &mut Interpreter, _host: &mut H) { + pop!(interpreter, memory_offset, code_offset, len); + let len = as_usize_or_fail!(interpreter, len); + gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); + if len == 0 { + return; + } + let memory_offset = as_usize_or_fail!(interpreter, memory_offset); + let code_offset = as_usize_saturated!(code_offset); + resize_memory!(interpreter, memory_offset, len); + + // Inform the optimizer that the bytecode cannot be EOF to remove a bounds check. + assume!(!interpreter.contract.bytecode.is_eof()); + // Note: this can't panic because we resized memory to fit. + interpreter.shared_memory.set_data( + memory_offset, + code_offset, + len, + &interpreter.contract.bytecode.original_bytes(), + ); +} + +pub fn calldataload(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, offset_ptr); + let mut word = B256::ZERO; + let offset = as_usize_saturated!(offset_ptr); + if offset < interpreter.contract.input.len() { + let count = 32.min(interpreter.contract.input.len() - offset); + // SAFETY: count is bounded by the calldata length. + // This is `word[..count].copy_from_slice(input[offset..offset + count])`, written using + // raw pointers as apparently the compiler cannot optimize the slice version, and using + // `get_unchecked` twice is uglier. + debug_assert!(count <= 32 && offset + count <= interpreter.contract.input.len()); + unsafe { + ptr::copy_nonoverlapping( + interpreter.contract.input.as_ptr().add(offset), + word.as_mut_ptr(), + count, + ) + }; + } + *offset_ptr = word.into(); +} + +pub fn calldatasize(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, U256::from(interpreter.contract.input.len())); +} + +pub fn callvalue(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, interpreter.contract.call_value); +} + +pub fn calldatacopy(interpreter: &mut Interpreter, _host: &mut H) { + pop!(interpreter, memory_offset, data_offset, len); + let len = as_usize_or_fail!(interpreter, len); + gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); + if len == 0 { + return; + } + let memory_offset = as_usize_or_fail!(interpreter, memory_offset); + let data_offset = as_usize_saturated!(data_offset); + resize_memory!(interpreter, memory_offset, len); + + // Note: this can't panic because we resized memory to fit. + interpreter.shared_memory.set_data( + memory_offset, + data_offset, + len, + &interpreter.contract.input, + ); +} + +/// EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY +pub fn returndatasize(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, BYZANTIUM); + gas!(interpreter, gas::BASE); + push!( + interpreter, + U256::from(interpreter.return_data_buffer.len()) + ); +} + +/// EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY +pub fn returndatacopy(interpreter: &mut Interpreter, _host: &mut H) { + check!(interpreter, BYZANTIUM); + pop!(interpreter, memory_offset, offset, len); + let len = as_usize_or_fail!(interpreter, len); + gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); + let data_offset = as_usize_saturated!(offset); + let data_end = data_offset.saturating_add(len); + if data_end > interpreter.return_data_buffer.len() { + interpreter.instruction_result = InstructionResult::OutOfOffset; + return; + } + if len != 0 { + let memory_offset = as_usize_or_fail!(interpreter, memory_offset); + resize_memory!(interpreter, memory_offset, len); + interpreter.shared_memory.set( + memory_offset, + &interpreter.return_data_buffer[data_offset..data_end], + ); + } +} + +/// Part of EOF ``. +pub fn returndataload(interpreter: &mut Interpreter, _host: &mut H) { + require_eof!(interpreter); + gas!(interpreter, gas::VERYLOW); + pop_top!(interpreter, offset); + let offset_usize = as_usize_or_fail!(interpreter, offset); + if offset_usize.saturating_add(32) > interpreter.return_data_buffer.len() { + // TODO(EOF) proper error. + interpreter.instruction_result = InstructionResult::OutOfOffset; + return; + } + *offset = + B256::from_slice(&interpreter.return_data_buffer[offset_usize..offset_usize + 32]).into(); +} + +pub fn gas(interpreter: &mut Interpreter, _host: &mut H) { + gas!(interpreter, gas::BASE); + push!(interpreter, U256::from(interpreter.gas.remaining())); +} + +#[cfg(test)] +mod test { + use super::*; + use crate::{ + opcode::{make_instruction_table, RETURNDATALOAD}, + primitives::{bytes, Bytecode, PragueSpec}, + DummyHost, Gas, + }; + + #[test] + fn returndataload() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + + let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( + [RETURNDATALOAD, RETURNDATALOAD, RETURNDATALOAD].into(), + )); + interp.is_eof = true; + interp.gas = Gas::new(10000); + + interp.stack.push(U256::from(0)).unwrap(); + interp.return_data_buffer = + bytes!("000000000000000400000000000000030000000000000002000000000000000100"); + interp.step(&table, &mut host); + assert_eq!( + interp.stack.data(), + &vec![U256::from_limbs([0x01, 0x02, 0x03, 0x04])] + ); + + let _ = interp.stack.pop(); + let _ = interp.stack.push(U256::from(1)); + + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Continue); + assert_eq!( + interp.stack.data(), + &vec![U256::from_limbs([0x0100, 0x0200, 0x0300, 0x0400])] + ); + + let _ = interp.stack.pop(); + let _ = interp.stack.push(U256::from(2)); + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::OutOfOffset); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/utility.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/utility.md new file mode 100644 index 00000000..a16bec7c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/instructions/utility.md @@ -0,0 +1,13 @@ +# ๐Ÿฆ€ utility.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/instructions/utility.rs) + +```rust +pub(crate) unsafe fn read_i16(ptr: *const u8) -> i16 { + i16::from_be_bytes(core::slice::from_raw_parts(ptr, 2).try_into().unwrap()) +} + +pub(crate) unsafe fn read_u16(ptr: *const u8) -> u16 { + u16::from_be_bytes(core::slice::from_raw_parts(ptr, 2).try_into().unwrap()) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter.md new file mode 100644 index 00000000..4baa1d20 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter.md @@ -0,0 +1,453 @@ +# ๐Ÿฆ€ interpreter.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter.rs) + +```rust +pub mod analysis; +mod contract; +#[cfg(feature = "serde")] +pub mod serde; +mod shared_memory; +mod stack; + +pub use contract::Contract; +pub use shared_memory::{num_words, SharedMemory, EMPTY_SHARED_MEMORY}; +pub use stack::{Stack, STACK_LIMIT}; + +use crate::EOFCreateOutcome; +use crate::{ + gas, primitives::Bytes, push, push_b256, return_ok, return_revert, CallOutcome, CreateOutcome, + FunctionStack, Gas, Host, InstructionResult, InterpreterAction, +}; +use core::cmp::min; +use revm_primitives::{Bytecode, Eof, U256}; +use std::borrow::ToOwned; + +/// EVM bytecode interpreter. +#[derive(Debug)] +pub struct Interpreter { + /// The current instruction pointer. + pub instruction_pointer: *const u8, + /// The gas state. + pub gas: Gas, + /// Contract information and invoking data + pub contract: Contract, + /// The execution control flag. If this is not set to `Continue`, the interpreter will stop + /// execution. + pub instruction_result: InstructionResult, + /// Currently run Bytecode that instruction result will point to. + /// Bytecode is owned by the contract. + pub bytecode: Bytes, + /// Whether we are Interpreting the Ethereum Object Format (EOF) bytecode. + /// This is local field that is set from `contract.is_eof()`. + pub is_eof: bool, + /// Is init flag for eof create + pub is_eof_init: bool, + /// Shared memory. + /// + /// Note: This field is only set while running the interpreter loop. + /// Otherwise it is taken and replaced with empty shared memory. + pub shared_memory: SharedMemory, + /// Stack. + pub stack: Stack, + /// EOF function stack. + pub function_stack: FunctionStack, + /// The return data buffer for internal calls. + /// It has multi usage: + /// + /// * It contains the output bytes of call sub call. + /// * When this interpreter finishes execution it contains the output bytes of this contract. + pub return_data_buffer: Bytes, + /// Whether the interpreter is in "staticcall" mode, meaning no state changes can happen. + pub is_static: bool, + /// Actions that the EVM should do. + /// + /// Set inside CALL or CREATE instructions and RETURN or REVERT instructions. Additionally those instructions will set + /// InstructionResult to CallOrCreate/Return/Revert so we know the reason. + pub next_action: InterpreterAction, +} + +impl Default for Interpreter { + fn default() -> Self { + Self::new(Contract::default(), 0, false) + } +} + +/// The result of an interpreter operation. +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] +pub struct InterpreterResult { + /// The result of the instruction execution. + pub result: InstructionResult, + /// The output of the instruction execution. + pub output: Bytes, + /// The gas usage information. + pub gas: Gas, +} + +impl Interpreter { + /// Create new interpreter + pub fn new(contract: Contract, gas_limit: u64, is_static: bool) -> Self { + if !contract.bytecode.is_execution_ready() { + panic!("Contract is not execution ready {:?}", contract.bytecode); + } + let is_eof = contract.bytecode.is_eof(); + let bytecode = contract.bytecode.bytecode().clone(); + Self { + instruction_pointer: bytecode.as_ptr(), + bytecode, + contract, + gas: Gas::new(gas_limit), + instruction_result: InstructionResult::Continue, + function_stack: FunctionStack::default(), + is_static, + is_eof, + is_eof_init: false, + return_data_buffer: Bytes::new(), + shared_memory: EMPTY_SHARED_MEMORY, + stack: Stack::new(), + next_action: InterpreterAction::None, + } + } + + /// Set set is_eof_init to true, this is used to enable `RETURNCONTRACT` opcode. + #[inline] + pub fn set_is_eof_init(&mut self) { + self.is_eof_init = true; + } + + #[inline] + pub fn eof(&self) -> Option<&Eof> { + self.contract.bytecode.eof() + } + + /// Test related helper + #[cfg(test)] + pub fn new_bytecode(bytecode: Bytecode) -> Self { + Self::new( + Contract::new( + Bytes::new(), + bytecode, + None, + crate::primitives::Address::default(), + crate::primitives::Address::default(), + U256::ZERO, + ), + 0, + false, + ) + } + + /// Load EOF code into interpreter. PC is assumed to be correctly set + pub(crate) fn load_eof_code(&mut self, idx: usize, pc: usize) { + // SAFETY: eof flag is true only if bytecode is Eof. + let Bytecode::Eof(eof) = &self.contract.bytecode else { + panic!("Expected EOF bytecode") + }; + let Some(code) = eof.body.code(idx) else { + panic!("Code not found") + }; + self.bytecode = code.clone(); + self.instruction_pointer = unsafe { self.bytecode.as_ptr().add(pc) }; + } + + /// Inserts the output of a `create` call into the interpreter. + /// + /// This function is used after a `create` call has been executed. It processes the outcome + /// of that call and updates the state of the interpreter accordingly. + /// + /// # Arguments + /// + /// * `create_outcome` - A `CreateOutcome` struct containing the results of the `create` call. + /// + /// # Behavior + /// + /// The function updates the `return_data_buffer` with the data from `create_outcome`. + /// Depending on the `InstructionResult` indicated by `create_outcome`, it performs one of the following: + /// + /// - `Ok`: Pushes the address from `create_outcome` to the stack, updates gas costs, and records any gas refunds. + /// - `Revert`: Pushes `U256::ZERO` to the stack and updates gas costs. + /// - `FatalExternalError`: Sets the `instruction_result` to `InstructionResult::FatalExternalError`. + /// - `Default`: Pushes `U256::ZERO` to the stack. + /// + /// # Side Effects + /// + /// - Updates `return_data_buffer` with the data from `create_outcome`. + /// - Modifies the stack by pushing values depending on the `InstructionResult`. + /// - Updates gas costs and records refunds in the interpreter's `gas` field. + /// - May alter `instruction_result` in case of external errors. + pub fn insert_create_outcome(&mut self, create_outcome: CreateOutcome) { + self.instruction_result = InstructionResult::Continue; + + let instruction_result = create_outcome.instruction_result(); + self.return_data_buffer = if instruction_result.is_revert() { + // Save data to return data buffer if the create reverted + create_outcome.output().to_owned() + } else { + // Otherwise clear it + Bytes::new() + }; + + match instruction_result { + return_ok!() => { + let address = create_outcome.address; + push_b256!(self, address.unwrap_or_default().into_word()); + self.gas.erase_cost(create_outcome.gas().remaining()); + self.gas.record_refund(create_outcome.gas().refunded()); + } + return_revert!() => { + push!(self, U256::ZERO); + self.gas.erase_cost(create_outcome.gas().remaining()); + } + InstructionResult::FatalExternalError => { + panic!("Fatal external error in insert_create_outcome"); + } + _ => { + push!(self, U256::ZERO); + } + } + } + + pub fn insert_eofcreate_outcome(&mut self, create_outcome: EOFCreateOutcome) { + let instruction_result = create_outcome.instruction_result(); + + self.return_data_buffer = if *instruction_result == InstructionResult::Revert { + // Save data to return data buffer if the create reverted + create_outcome.output().to_owned() + } else { + // Otherwise clear it. Note that RETURN opcode should abort. + Bytes::new() + }; + + match instruction_result { + InstructionResult::ReturnContract => { + push_b256!(self, create_outcome.address.into_word()); + self.gas.erase_cost(create_outcome.gas().remaining()); + self.gas.record_refund(create_outcome.gas().refunded()); + } + return_revert!() => { + push!(self, U256::ZERO); + self.gas.erase_cost(create_outcome.gas().remaining()); + } + InstructionResult::FatalExternalError => { + panic!("Fatal external error in insert_eofcreate_outcome"); + } + _ => { + push!(self, U256::ZERO); + } + } + } + + /// Inserts the outcome of a call into the virtual machine's state. + /// + /// This function takes the result of a call, represented by `CallOutcome`, + /// and updates the virtual machine's state accordingly. It involves updating + /// the return data buffer, handling gas accounting, and setting the memory + /// in shared storage based on the outcome of the call. + /// + /// # Arguments + /// + /// * `shared_memory` - A mutable reference to the shared memory used by the virtual machine. + /// * `call_outcome` - The outcome of the call to be processed, containing details such as + /// instruction result, gas information, and output data. + /// + /// # Behavior + /// + /// The function first copies the output data from the call outcome to the virtual machine's + /// return data buffer. It then checks the instruction result from the call outcome: + /// + /// - `return_ok!()`: Processes successful execution, refunds gas, and updates shared memory. + /// - `return_revert!()`: Handles a revert by only updating the gas usage and shared memory. + /// - `InstructionResult::FatalExternalError`: Sets the instruction result to a fatal external error. + /// - Any other result: No specific action is taken. + pub fn insert_call_outcome( + &mut self, + shared_memory: &mut SharedMemory, + call_outcome: CallOutcome, + ) { + self.instruction_result = InstructionResult::Continue; + self.return_data_buffer.clone_from(call_outcome.output()); + + let out_offset = call_outcome.memory_start(); + let out_len = call_outcome.memory_length(); + + let target_len = min(out_len, self.return_data_buffer.len()); + match call_outcome.instruction_result() { + return_ok!() => { + // return unspend gas. + let remaining = call_outcome.gas().remaining(); + let refunded = call_outcome.gas().refunded(); + self.gas.erase_cost(remaining); + self.gas.record_refund(refunded); + shared_memory.set(out_offset, &self.return_data_buffer[..target_len]); + push!(self, U256::from(1)); + } + return_revert!() => { + self.gas.erase_cost(call_outcome.gas().remaining()); + shared_memory.set(out_offset, &self.return_data_buffer[..target_len]); + push!(self, U256::ZERO); + } + InstructionResult::FatalExternalError => { + panic!("Fatal external error in insert_call_outcome"); + } + _ => { + push!(self, U256::ZERO); + } + } + } + + /// Returns the opcode at the current instruction pointer. + #[inline] + pub fn current_opcode(&self) -> u8 { + unsafe { *self.instruction_pointer } + } + + /// Returns a reference to the contract. + #[inline] + pub fn contract(&self) -> &Contract { + &self.contract + } + + /// Returns a reference to the interpreter's gas state. + #[inline] + pub fn gas(&self) -> &Gas { + &self.gas + } + + /// Returns a reference to the interpreter's stack. + #[inline] + pub fn stack(&self) -> &Stack { + &self.stack + } + + /// Returns the current program counter. + #[inline] + pub fn program_counter(&self) -> usize { + // SAFETY: `instruction_pointer` should be at an offset from the start of the bytecode. + // In practice this is always true unless a caller modifies the `instruction_pointer` field manually. + unsafe { self.instruction_pointer.offset_from(self.bytecode.as_ptr()) as usize } + } + + /// Executes the instruction at the current instruction pointer. + /// + /// Internally it will increment instruction pointer by one. + #[inline] + pub(crate) fn step(&mut self, instruction_table: &[FN; 256], host: &mut H) + where + FN: Fn(&mut Interpreter, &mut H), + { + // Get current opcode. + let opcode = unsafe { *self.instruction_pointer }; + + // SAFETY: In analysis we are doing padding of bytecode so that we are sure that last + // byte instruction is STOP so we are safe to just increment program_counter bcs on last instruction + // it will do noop and just stop execution of this contract + self.instruction_pointer = unsafe { self.instruction_pointer.offset(1) }; + + // execute instruction. + (instruction_table[opcode as usize])(self, host) + } + + /// Take memory and replace it with empty memory. + pub fn take_memory(&mut self) -> SharedMemory { + core::mem::replace(&mut self.shared_memory, EMPTY_SHARED_MEMORY) + } + + /// Executes the interpreter until it returns or stops. + pub fn run( + &mut self, + shared_memory: SharedMemory, + instruction_table: &[FN; 256], + host: &mut H, + ) -> InterpreterAction + where + FN: Fn(&mut Interpreter, &mut H), + { + self.next_action = InterpreterAction::None; + self.shared_memory = shared_memory; + // main loop + while self.instruction_result == InstructionResult::Continue { + self.step(instruction_table, host); + } + + // Return next action if it is some. + if self.next_action.is_some() { + return core::mem::take(&mut self.next_action); + } + // If not, return action without output as it is a halt. + InterpreterAction::Return { + result: InterpreterResult { + result: self.instruction_result, + // return empty bytecode + output: Bytes::new(), + gas: self.gas, + }, + } + } + + /// Resize the memory to the new size. Returns whether the gas was enough to resize the memory. + #[inline] + #[must_use] + pub fn resize_memory(&mut self, new_size: usize) -> bool { + resize_memory(&mut self.shared_memory, &mut self.gas, new_size) + } +} + +impl InterpreterResult { + /// Returns whether the instruction result is a success. + #[inline] + pub const fn is_ok(&self) -> bool { + self.result.is_ok() + } + + /// Returns whether the instruction result is a revert. + #[inline] + pub const fn is_revert(&self) -> bool { + self.result.is_revert() + } + + /// Returns whether the instruction result is an error. + #[inline] + pub const fn is_error(&self) -> bool { + self.result.is_error() + } +} + +/// Resize the memory to the new size. Returns whether the gas was enough to resize the memory. +#[inline(never)] +#[cold] +#[must_use] +pub fn resize_memory(memory: &mut SharedMemory, gas: &mut Gas, new_size: usize) -> bool { + let new_words = num_words(new_size as u64); + let new_cost = gas::memory_gas(new_words); + let current_cost = memory.current_expansion_cost(); + let cost = new_cost - current_cost; + let success = gas.record_cost(cost); + if success { + memory.resize((new_words as usize) * 32); + } + success +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{opcode::InstructionTable, DummyHost}; + use revm_primitives::CancunSpec; + + #[test] + fn object_safety() { + let mut interp = Interpreter::new(Contract::default(), u64::MAX, false); + + let mut host = crate::DummyHost::default(); + let table: InstructionTable = + crate::opcode::make_instruction_table::(); + let _ = interp.run(EMPTY_SHARED_MEMORY, &table, &mut host); + + let host: &mut dyn Host = &mut host as &mut dyn Host; + let table: InstructionTable = + crate::opcode::make_instruction_table::(); + let _ = interp.run(EMPTY_SHARED_MEMORY, &table, host); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/analysis.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/analysis.md new file mode 100644 index 00000000..12521144 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/analysis.md @@ -0,0 +1,598 @@ +# ๐Ÿฆ€ analysis.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter/analysis.rs) + +```rust +use revm_primitives::{eof::EofDecodeError, HashSet}; + +use crate::{ + instructions::utility::{read_i16, read_u16}, + opcode, + primitives::{ + bitvec::prelude::{bitvec, BitVec, Lsb0}, + eof::TypesSection, + legacy::JumpTable, + Bytecode, Bytes, Eof, LegacyAnalyzedBytecode, + }, + OPCODE_INFO_JUMPTABLE, STACK_LIMIT, +}; +use std::{sync::Arc, vec, vec::Vec}; + +const EOF_NON_RETURNING_FUNCTION: u8 = 0x80; + +/// Perform bytecode analysis. +/// +/// The analysis finds and caches valid jump destinations for later execution as an optimization step. +/// +/// If the bytecode is already analyzed, it is returned as-is. +#[inline] +pub fn to_analysed(bytecode: Bytecode) -> Bytecode { + let (bytes, len) = match bytecode { + Bytecode::LegacyRaw(bytecode) => { + let len = bytecode.len(); + let mut padded_bytecode = Vec::with_capacity(len + 33); + padded_bytecode.extend_from_slice(&bytecode); + padded_bytecode.resize(len + 33, 0); + (Bytes::from(padded_bytecode), len) + } + n => return n, + }; + let jump_table = analyze(bytes.as_ref()); + + Bytecode::LegacyAnalyzed(LegacyAnalyzedBytecode::new(bytes, len, jump_table)) +} + +/// Analyze bytecode to build a jump map. +fn analyze(code: &[u8]) -> JumpTable { + let mut jumps: BitVec = bitvec![u8, Lsb0; 0; code.len()]; + + let range = code.as_ptr_range(); + let start = range.start; + let mut iterator = start; + let end = range.end; + while iterator < end { + let opcode = unsafe { *iterator }; + if opcode::JUMPDEST == opcode { + // SAFETY: jumps are max length of the code + unsafe { jumps.set_unchecked(iterator.offset_from(start) as usize, true) } + iterator = unsafe { iterator.offset(1) }; + } else { + let push_offset = opcode.wrapping_sub(opcode::PUSH1); + if push_offset < 32 { + // SAFETY: iterator access range is checked in the while loop + iterator = unsafe { iterator.offset((push_offset + 2) as isize) }; + } else { + // SAFETY: iterator access range is checked in the while loop + iterator = unsafe { iterator.offset(1) }; + } + } + } + + JumpTable(Arc::new(jumps)) +} + +pub fn validate_raw_eof(bytecode: Bytes) -> Result { + let eof = Eof::decode(bytecode)?; + validate_eof(&eof)?; + Ok(eof) +} + +/// Validate Eof structures. +pub fn validate_eof(eof: &Eof) -> Result<(), EofError> { + // clone is cheap as it is Bytes and a header. + let mut queue = vec![eof.clone()]; + + while let Some(eof) = queue.pop() { + // iterate over types + validate_eof_codes(&eof)?; + // iterate over containers, convert them to Eof and add to analyze_eof + for container in eof.body.container_section { + queue.push(Eof::decode(container)?); + } + } + + // Eof is valid + Ok(()) +} + +/// Validate EOF +pub fn validate_eof_codes(eof: &Eof) -> Result<(), EofValidationError> { + let mut queued_codes = vec![false; eof.body.code_section.len()]; + if eof.body.code_section.len() != eof.body.types_section.len() { + return Err(EofValidationError::InvalidTypesSection); + } + + if eof.body.code_section.is_empty() { + // no code sections. This should be already checked in decode. + return Err(EofValidationError::NoCodeSections); + } + // first section is default one. + queued_codes[0] = true; + + // the first code section must have a type signature + // (0, 0x80, max_stack_height) (0 inputs non-returning function) + let first_types = &eof.body.types_section[0]; + if first_types.inputs != 0 || first_types.outputs != EOF_NON_RETURNING_FUNCTION { + return Err(EofValidationError::InvalidTypesSection); + } + + // start validation from code section 0. + let mut queue = vec![0]; + while let Some(index) = queue.pop() { + let code = &eof.body.code_section[index]; + let accessed_codes = validate_eof_code( + code, + eof.header.data_size as usize, + index, + eof.body.container_section.len(), + &eof.body.types_section, + )?; + + // queue accessed codes. + accessed_codes.into_iter().for_each(|i| { + if !queued_codes[i] { + queued_codes[i] = true; + queue.push(i); + } + }); + } + // iterate over accessed codes and check if all are accessed. + if queued_codes.into_iter().any(|x| !x) { + return Err(EofValidationError::CodeSectionNotAccessed); + } + + Ok(()) +} + +/// EOF Error. +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +pub enum EofError { + Decode(EofDecodeError), + Validation(EofValidationError), +} + +impl From for EofError { + fn from(err: EofDecodeError) -> Self { + EofError::Decode(err) + } +} + +impl From for EofError { + fn from(err: EofValidationError) -> Self { + EofError::Validation(err) + } +} + +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +pub enum EofValidationError { + FalsePossitive, + /// Opcode is not known. It is not defined in the opcode table. + UnknownOpcode, + /// Opcode is disabled in EOF. For example JUMP, JUMPI, etc. + OpcodeDisabled, + /// Every instruction inside bytecode should be forward accessed. + /// Forward access can be a jump or sequential opcode. + /// In case after terminal opcode there should be a forward jump. + InstructionNotForwardAccessed, + /// Bytecode is too small and is missing immediate bytes for instruction. + MissingImmediateBytes, + /// Similar to [`EofValidationError::MissingImmediateBytes`] but for special case of RJUMPV immediate bytes. + MissingRJUMPVImmediateBytes, + /// Invalid jump into immediate bytes. + JumpToImmediateBytes, + /// Invalid jump into immediate bytes. + BackwardJumpToImmediateBytes, + /// MaxIndex in RJUMPV can't be zero. Zero max index makes it RJUMPI. + RJUMPVZeroMaxIndex, + /// Jump with zero offset would make a jump to next opcode, it does not make sense. + JumpZeroOffset, + /// EOFCREATE points to container out of bounds. + EOFCREATEInvalidIndex, + /// CALLF section out of bounds. + CodeSectionOutOfBounds, + /// CALLF to non returning function is not allowed. + CALLFNonReturningFunction, + /// CALLF stack overflow. + StackOverflow, + /// JUMPF needs to have enough outputs. + JUMPFEnoughOutputs, + /// JUMPF Stack + JUMPFStackHigherThanOutputs, + /// DATA load out of bounds. + DataLoadOutOfBounds, + /// RETF biggest stack num more then outputs. + RETFBiggestStackNumMoreThenOutputs, + /// Stack requirement is more than smallest stack items. + StackUnderflow, + /// Smallest stack items is more than types output. + TypesStackUnderflow, + /// Jump out of bounds. + JumpUnderflow, + /// Jump to out of bounds. + JumpOverflow, + /// Backward jump should have same smallest and biggest stack items. + BackwardJumpBiggestNumMismatch, + /// Backward jump should have same smallest and biggest stack items. + BackwardJumpSmallestNumMismatch, + /// Last instruction should be terminating. + LastInstructionNotTerminating, + /// Code section not accessed. + CodeSectionNotAccessed, + /// Types section invalid + InvalidTypesSection, + /// First types section is invalid. + /// It should have inputs 0 and outputs 0x80. + InvalidFirstTypesSection, + /// Max stack element mismatch. + MaxStackMismatch, + /// No code sections present + NoCodeSections, +} + +/// Validates that: +/// * All instructions are valid. +/// * It ends with a terminating instruction or RJUMP. +/// * All instructions are accessed by forward jumps or . +/// +/// Validate stack requirements and if all codes sections are used. +/// +/// TODO mark accessed Types/Codes +/// +/// Preconditions: +/// * Jump destinations are valid. +/// * All instructions are valid and well formed. +/// * All instruction is accessed by forward jumps. +/// * Bytecode is valid and ends with terminating instruction. +/// +/// Preconditions are checked in `validate_eof_bytecode`. +pub fn validate_eof_code( + code: &[u8], + data_size: usize, + this_types_index: usize, + num_of_containers: usize, + types: &[TypesSection], +) -> Result, EofValidationError> { + let mut accessed_codes = HashSet::::new(); + let this_types = &types[this_types_index]; + + #[derive(Debug, Copy, Clone)] + struct InstructionInfo { + /// Is immediate byte, jumps can't happen on this part of code. + is_immediate: bool, + /// Have forward jump to this opcode. Used to check if opcode + /// after termination is accessed. + is_jumpdest: bool, + /// Smallest number of stack items accessed by jumps or sequential opcodes. + smallest: i32, + /// Biggest number of stack items accessed by jumps or sequential opcodes. + biggest: i32, + } + + impl InstructionInfo { + #[inline] + fn mark_as_immediate(&mut self) -> Result<(), EofValidationError> { + if self.is_jumpdest { + // Jump to immediate bytes. + return Err(EofValidationError::JumpToImmediateBytes); + } + self.is_immediate = true; + Ok(()) + } + } + + impl Default for InstructionInfo { + fn default() -> Self { + Self { + is_immediate: false, + is_jumpdest: false, + smallest: i32::MAX, + biggest: i32::MIN, + } + } + } + + // all bytes that are intermediate. + let mut jumps = vec![InstructionInfo::default(); code.len()]; + let mut is_after_termination = false; + + let mut next_smallest = this_types.inputs as i32; + let mut next_biggest = this_types.inputs as i32; + + let mut i = 0; + // We can check validity and jump destinations in one pass. + while i < code.len() { + let op = code[i]; + let opcode = &OPCODE_INFO_JUMPTABLE[op as usize]; + + let Some(opcode) = opcode else { + // err unknown opcode. + return Err(EofValidationError::UnknownOpcode); + }; + + if opcode.is_disabled_in_eof() { + // Opcode is disabled in EOF + return Err(EofValidationError::OpcodeDisabled); + } + + let this_instruction = &mut jumps[i]; + + // update biggest/smallest values for next instruction only if it is not after termination. + if !is_after_termination { + this_instruction.smallest = core::cmp::min(this_instruction.smallest, next_smallest); + this_instruction.biggest = core::cmp::max(this_instruction.biggest, next_biggest); + } + + let this_instruction = *this_instruction; + + // Opcodes after termination should be accessed by forward jumps. + if is_after_termination && !this_instruction.is_jumpdest { + // opcode after termination was not accessed. + return Err(EofValidationError::InstructionNotForwardAccessed); + } + is_after_termination = opcode.is_terminating(); + + // mark immediate as non-jumpable. RJUMPV is special case covered later. + if opcode.immediate_size() != 0 { + // check if the opcode immediate are within the bounds of the code + if i + opcode.immediate_size() as usize >= code.len() { + // Malfunctional code + return Err(EofValidationError::MissingImmediateBytes); + } + + // mark immediate bytes as non-jumpable. + for imm in 1..opcode.immediate_size() as usize + 1 { + // SAFETY: immediate size is checked above. + jumps[i + imm].mark_as_immediate()?; + } + } + // IO diff used to generate next instruction smallest/biggest value. + let mut stack_io_diff = opcode.io_diff() as i32; + // how many stack items are required for this opcode. + let mut stack_requirement = opcode.inputs() as i32; + // additional immediate bytes for RJUMPV, it has dynamic vtable. + let mut rjumpv_additional_immediates = 0; + // If opcodes is RJUMP, RJUMPI or RJUMPV then this will have absolute jumpdest. + let mut absolute_jumpdest = vec![]; + match op { + opcode::RJUMP | opcode::RJUMPI => { + let offset = unsafe { read_i16(code.as_ptr().add(i + 1)) } as isize; + absolute_jumpdest = vec![offset + 3 + i as isize]; + // RJUMP is considered a terminating opcode. + } + opcode::RJUMPV => { + // code length for RJUMPV is checked with immediate size. + let max_index = code[i + 1] as usize; + let len = max_index + 1; + // and max_index+1 is to get size of vtable as index starts from 0. + rjumpv_additional_immediates = len * 2; + + // +1 is for max_index byte + if i + 1 + rjumpv_additional_immediates >= code.len() { + // Malfunctional code RJUMPV vtable is not complete + return Err(EofValidationError::MissingRJUMPVImmediateBytes); + } + + // Mark vtable as immediate, max_index was already marked. + for imm in 0..rjumpv_additional_immediates { + // SAFETY: immediate size is checked above. + jumps[i + 2 + imm].mark_as_immediate()?; + } + + let mut jumps = Vec::with_capacity(len); + for vtablei in 0..len { + let offset = + unsafe { read_i16(code.as_ptr().add(i + 2 + 2 * vtablei)) } as isize; + jumps.push(offset + i as isize + 2 + rjumpv_additional_immediates as isize); + } + absolute_jumpdest = jumps + } + opcode::CALLF => { + let section_i = unsafe { read_u16(code.as_ptr().add(i + 1)) } as usize; + let Some(target_types) = types.get(section_i) else { + // code section out of bounds. + return Err(EofValidationError::CodeSectionOutOfBounds); + }; + + if target_types.outputs == EOF_NON_RETURNING_FUNCTION { + // callf to non returning function is not allowed + return Err(EofValidationError::CALLFNonReturningFunction); + } + // stack input for this opcode is the input of the called code. + stack_requirement = target_types.inputs as i32; + // stack diff depends on input/output of the called code. + stack_io_diff = target_types.io_diff(); + // mark called code as accessed. + accessed_codes.insert(section_i); + + // we decrement by `types.inputs` as they are considered as send + // to the called code and included in types.max_stack_size. + if this_instruction.biggest - stack_requirement + target_types.max_stack_size as i32 + > STACK_LIMIT as i32 + { + // if stack max items + called code max stack size + return Err(EofValidationError::StackOverflow); + } + } + opcode::JUMPF => { + let target_index = unsafe { read_u16(code.as_ptr().add(i + 1)) } as usize; + // targeted code needs to have zero outputs (be non returning). + let Some(target_types) = types.get(target_index) else { + // code section out of bounds. + return Err(EofValidationError::CodeSectionOutOfBounds); + }; + + // we decrement types.inputs as they are considered send to the called code. + // and included in types.max_stack_size. + if this_instruction.biggest - target_types.inputs as i32 + + target_types.max_stack_size as i32 + > STACK_LIMIT as i32 + { + // stack overflow + return Err(EofValidationError::StackOverflow); + } + accessed_codes.insert(target_index); + + if target_types.outputs == EOF_NON_RETURNING_FUNCTION { + // if it is not returning + stack_requirement = target_types.inputs as i32; + } else { + // check if target code produces enough outputs. + if this_types.outputs < target_types.outputs { + return Err(EofValidationError::JUMPFEnoughOutputs); + } + + stack_requirement = this_types.outputs as i32 + target_types.inputs as i32 + - target_types.outputs as i32; + + // Stack requirement needs to more than this instruction biggest stack number. + if this_instruction.biggest > stack_requirement { + return Err(EofValidationError::JUMPFStackHigherThanOutputs); + } + + // if this instruction max + target_types max is more then stack limit. + if this_instruction.biggest + stack_requirement > STACK_LIMIT as i32 { + return Err(EofValidationError::StackOverflow); + } + } + } + opcode::EOFCREATE => { + let index = code[i + 1] as usize; + if index >= num_of_containers { + // code section out of bounds. + return Err(EofValidationError::EOFCREATEInvalidIndex); + } + } + opcode::DATALOADN => { + let index = unsafe { read_u16(code.as_ptr().add(i + 1)) } as isize; + if data_size < 32 || index > data_size as isize - 32 { + // data load out of bounds. + return Err(EofValidationError::DataLoadOutOfBounds); + } + } + opcode::RETF => { + stack_requirement = this_types.outputs as i32; + if this_instruction.biggest > stack_requirement { + return Err(EofValidationError::RETFBiggestStackNumMoreThenOutputs); + } + } + opcode::DUPN => { + stack_requirement = code[i + 1] as i32 + 1; + } + opcode::SWAPN => { + stack_requirement = code[i + 1] as i32 + 2; + } + opcode::EXCHANGE => { + let imm = code[i + 1]; + let n = (imm >> 4) + 1; + let m = (imm & 0x0F) + 1; + stack_requirement = n as i32 + m as i32 + 1; + } + _ => {} + } + // check if stack requirement is more than smallest stack items. + if stack_requirement > this_instruction.smallest { + // opcode requirement is more than smallest stack items. + return Err(EofValidationError::StackUnderflow); + } + + next_smallest = this_instruction.smallest + stack_io_diff; + next_biggest = this_instruction.biggest + stack_io_diff; + + // check if jumpdest are correct and mark forward jumps. + for absolute_jump in absolute_jumpdest { + if absolute_jump < 0 { + // jump out of bounds. + return Err(EofValidationError::JumpUnderflow); + } + if absolute_jump >= code.len() as isize { + // jump to out of bounds + return Err(EofValidationError::JumpOverflow); + } + // fine to cast as bounds are checked. + let absolute_jump = absolute_jump as usize; + + let target_jump = &mut jumps[absolute_jump]; + if target_jump.is_immediate { + // Jump target is immediate byte. + return Err(EofValidationError::BackwardJumpToImmediateBytes); + } + + // needed to mark forward jumps. It does not do anything for backward jumps. + target_jump.is_jumpdest = true; + + if absolute_jump <= i { + // backward jumps should have same smallest and biggest stack items. + if target_jump.biggest != next_biggest { + // wrong jumpdest. + return Err(EofValidationError::BackwardJumpBiggestNumMismatch); + } + if target_jump.smallest != next_smallest { + // wrong jumpdest. + return Err(EofValidationError::BackwardJumpSmallestNumMismatch); + } + } else { + // forward jumps can make min even smallest size + // while biggest num is needed to check stack overflow + target_jump.smallest = core::cmp::min(target_jump.smallest, next_smallest); + target_jump.biggest = core::cmp::max(target_jump.biggest, next_biggest); + } + } + + // additional immediate are from RJUMPV vtable. + i += 1 + opcode.immediate_size() as usize + rjumpv_additional_immediates; + } + + // last opcode should be terminating + if !is_after_termination { + // wrong termination. + return Err(EofValidationError::LastInstructionNotTerminating); + } + // TODO integrate max so we dont need to iterate again + let mut max_stack_requirement = 0; + for opcode in jumps { + max_stack_requirement = core::cmp::max(opcode.biggest, max_stack_requirement); + } + + if max_stack_requirement != types[this_types_index].max_stack_size as i32 { + // stack overflow + return Err(EofValidationError::MaxStackMismatch); + } + + Ok(accessed_codes) +} + +#[cfg(test)] +mod test { + use super::*; + use revm_primitives::hex; + + #[test] + fn test1() { + // result:Result { result: false, exception: Some("EOF_ConflictingStackHeight") } + let err = + validate_raw_eof(hex!("ef0001010004020001000704000000008000016000e200fffc00").into()); + assert!(err.is_err(), "{err:#?}"); + } + + #[test] + fn test2() { + // result:Result { result: false, exception: Some("EOF_InvalidNumberOfOutputs") } + let err = + validate_raw_eof(hex!("ef000101000c02000300040004000204000000008000020002000100010001e30001005fe500025fe4").into()); + assert!(err.is_ok(), "{err:#?}"); + } + + #[test] + fn test3() { + // result:Result { result: false, exception: Some("EOF_InvalidNumberOfOutputs") } + let err = + validate_raw_eof(hex!("ef000101000c02000300040008000304000000008000020002000503010003e30001005f5f5f5f5fe500025050e4").into()); + assert_eq!( + err, + Err(EofError::Validation( + EofValidationError::JUMPFStackHigherThanOutputs + )) + ); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/contract.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/contract.md new file mode 100644 index 00000000..a78c74b4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/contract.md @@ -0,0 +1,98 @@ +# ๐Ÿฆ€ contract.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter/contract.rs) + +```rust +use super::analysis::to_analysed; +use crate::{ + primitives::{Address, Bytecode, Bytes, Env, TransactTo, B256, U256}, + CallInputs, +}; + +/// EVM contract information. +#[derive(Clone, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Contract { + /// Contracts data + pub input: Bytes, + /// Bytecode contains contract code, size of original code, analysis with gas block and jump table. + /// Note that current code is extended with push padding and STOP at end. + pub bytecode: Bytecode, + /// Bytecode hash for legacy. For EOF this would be None. + pub hash: Option, + /// Target address of the account. Storage of this address is going to be modified. + pub target_address: Address, + /// Caller of the EVM. + pub caller: Address, + /// Value send to contract from transaction or from CALL opcodes. + pub call_value: U256, +} + +impl Contract { + /// Instantiates a new contract by analyzing the given bytecode. + #[inline] + pub fn new( + input: Bytes, + bytecode: Bytecode, + hash: Option, + target_address: Address, + caller: Address, + call_value: U256, + ) -> Self { + let bytecode = to_analysed(bytecode); + + Self { + input, + bytecode, + hash, + target_address, + caller, + call_value, + } + } + + /// Creates a new contract from the given [`Env`]. + #[inline] + pub fn new_env(env: &Env, bytecode: Bytecode, hash: Option) -> Self { + let contract_address = match env.tx.transact_to { + TransactTo::Call(caller) => caller, + TransactTo::Create => Address::ZERO, + }; + Self::new( + env.tx.data.clone(), + bytecode, + hash, + contract_address, + env.tx.caller, + env.tx.value, + ) + } + + /// Creates a new contract from the given inputs. + #[inline] + pub fn new_with_context( + input: Bytes, + bytecode: Bytecode, + hash: Option, + call_context: &CallInputs, + ) -> Self { + Self::new( + input, + bytecode, + hash, + call_context.target_address, + call_context.caller, + call_context.call_value(), + ) + } + + /// Returns whether the given position is a valid jump destination. + #[inline] + pub fn is_valid_jump(&self, pos: usize) -> bool { + self.bytecode + .legacy_jump_table() + .map(|i| i.is_valid(pos)) + .unwrap_or(false) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/serde.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/serde.md new file mode 100644 index 00000000..e28c5dea --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/serde.md @@ -0,0 +1,248 @@ +# ๐Ÿฆ€ serde.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter/serde.rs) + +```rust +use crate::{ + Contract, FunctionStack, Gas, InstructionResult, InterpreterAction, SharedMemory, Stack, +}; + +use super::Interpreter; +use revm_primitives::Bytes; +use serde::de::{self, MapAccess, Visitor}; +use serde::ser::SerializeStruct; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::fmt; + +impl Serialize for Interpreter { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut state = serializer.serialize_struct("Interpreter", 8)?; + // Convert the instruction pointer to a usize for serialization + let program_counter = self.program_counter(); + state.serialize_field("program_counter", &program_counter)?; + state.serialize_field("gas", &self.gas)?; + state.serialize_field("contract", &self.contract)?; + state.serialize_field("instruction_result", &self.instruction_result)?; + state.serialize_field("bytecode", &self.bytecode)?; + state.serialize_field("is_eof", &self.is_eof)?; + state.serialize_field("is_eof_init", &self.is_eof_init)?; + state.serialize_field("shared_memory", &self.shared_memory)?; + state.serialize_field("stack", &self.stack)?; + state.serialize_field("function_stack", &self.function_stack)?; + state.serialize_field("return_data_buffer", &self.return_data_buffer)?; + state.serialize_field("is_static", &self.is_static)?; + state.serialize_field("next_action", &self.next_action)?; + state.end() + } +} + +impl<'de> Deserialize<'de> for Interpreter { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct InterpreterVisitor; + + #[derive(serde::Deserialize)] + #[serde(field_identifier, rename_all = "lowercase")] + enum InterpreterFields { + ProgramCounter, + Gas, + Contract, + InstructionResult, + Bytecode, + IsEof, + IsEofInit, + SharedMemory, + Stack, + FunctionStack, + ReturnDataBuffer, + IsStatic, + NextAction, + } + + #[allow(clippy::too_many_arguments)] + fn rebuild_interp( + program_counter: isize, + gas: Gas, + contract: Contract, + instruction_result: InstructionResult, + bytecode: Bytes, + is_eof: bool, + is_eof_init: bool, + shared_memory: SharedMemory, + stack: Stack, + function_stack: FunctionStack, + return_data_buffer: Bytes, + is_static: bool, + next_action: InterpreterAction, + ) -> Result { + // Reconstruct the instruction pointer from usize + if program_counter < 0 || program_counter >= bytecode.len() as isize { + return Err("program_counter index out of range"); + } + + // SAFETY: range of program_counter checked above + let instruction_pointer = unsafe { bytecode.as_ptr().offset(program_counter) }; + + // Construct and return the Interpreter instance + Ok(Interpreter { + instruction_pointer, + gas, + contract, + instruction_result, + bytecode, + is_eof, + is_eof_init, + shared_memory, + stack, + function_stack, + return_data_buffer, + is_static, + next_action, + }) + } + + impl<'de> Visitor<'de> for InterpreterVisitor { + type Value = Interpreter; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("struct Interpreter") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: de::SeqAccess<'de>, + { + macro_rules! extract_field { + ($i:ident, $idx:expr) => { + let $i = seq + .next_element()? + .ok_or_else(|| de::Error::invalid_length($idx, &self))?; + }; + } + extract_field!(instruction_pointer, 0); + extract_field!(gas, 1); + extract_field!(contract, 2); + extract_field!(instruction_result, 3); + extract_field!(bytecode, 4); + extract_field!(is_eof, 5); + extract_field!(is_eof_init, 6); + extract_field!(shared_memory, 7); + extract_field!(stack, 8); + extract_field!(function_stack, 9); + extract_field!(return_data_buffer, 10); + extract_field!(is_static, 11); + extract_field!(next_action, 12); + rebuild_interp( + instruction_pointer, + gas, + contract, + instruction_result, + bytecode, + is_eof, + is_eof_init, + shared_memory, + stack, + function_stack, + return_data_buffer, + is_static, + next_action, + ) + .map_err(de::Error::custom) + } + + fn visit_map(self, mut map: V) -> Result + where + V: MapAccess<'de>, + { + macro_rules! parse_map { + ( $(($enum:pat, $var_name:ident)),* ) => { + $( + let mut $var_name = None; + )* + while let Some(key) = map.next_key()? { + match key { + $( + $enum => { + $var_name = Some(map.next_value()?); + } + )* + } + } + $( + let $var_name = $var_name.ok_or_else(|| de::Error::missing_field(stringify!($var_name)))?; + )* + }; + } + parse_map!( + (InterpreterFields::ProgramCounter, program_counter), + (InterpreterFields::Gas, gas), + (InterpreterFields::Contract, contract), + (InterpreterFields::InstructionResult, instruction_result), + (InterpreterFields::Bytecode, bytecode), + (InterpreterFields::IsEof, is_eof), + (InterpreterFields::IsEofInit, is_eof_init), + (InterpreterFields::SharedMemory, shared_memory), + (InterpreterFields::Stack, stack), + (InterpreterFields::FunctionStack, function_stack), + (InterpreterFields::ReturnDataBuffer, return_data_buffer), + (InterpreterFields::IsStatic, is_static), + (InterpreterFields::NextAction, next_action) + ); + + rebuild_interp( + program_counter, + gas, + contract, + instruction_result, + bytecode, + is_eof, + is_eof_init, + shared_memory, + stack, + function_stack, + return_data_buffer, + is_static, + next_action, + ) + .map_err(de::Error::custom) + } + } + + const FIELDS: &[&str] = &[ + "program_counter", + "gas", + "contract", + "instruction_result", + "bytecode", + "is_eof", + "is_eof_init", + "shared_memory", + "stack", + "function_stack", + "return_data_buffer", + "is_static", + "next_action", + ]; + + deserializer.deserialize_struct("Interpreter", FIELDS, InterpreterVisitor) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_serde() { + let interp = Interpreter::new(Contract::default(), u64::MAX, false); + let serialized = bincode::serialize(&interp).unwrap(); + let de: Interpreter = bincode::deserialize(&serialized).unwrap(); + assert_eq!(interp.program_counter(), de.program_counter()); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/shared_memory.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/shared_memory.md new file mode 100644 index 00000000..2497674f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/shared_memory.md @@ -0,0 +1,413 @@ +# ๐Ÿฆ€ shared_memory.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter/shared_memory.rs) + +```rust +use core::{cmp::min, fmt, ops::Range}; +use revm_primitives::{B256, U256}; +use std::vec::Vec; + +/// A sequential memory shared between calls, which uses +/// a `Vec` for internal representation. +/// A [SharedMemory] instance should always be obtained using +/// the `new` static method to ensure memory safety. +#[derive(Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SharedMemory { + /// The underlying buffer. + buffer: Vec, + /// Memory checkpoints for each depth. + /// Invariant: these are always in bounds of `data`. + checkpoints: Vec, + /// Invariant: equals `self.checkpoints.last()` + last_checkpoint: usize, + /// Memory limit. See [`CfgEnv`](revm_primitives::CfgEnv). + #[cfg(feature = "memory_limit")] + memory_limit: u64, +} + +/// Empty shared memory. +/// +/// Used as placeholder inside Interpreter when it is not running. +pub const EMPTY_SHARED_MEMORY: SharedMemory = SharedMemory { + buffer: Vec::new(), + checkpoints: Vec::new(), + last_checkpoint: 0, + #[cfg(feature = "memory_limit")] + memory_limit: u64::MAX, +}; + +impl fmt::Debug for SharedMemory { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SharedMemory") + .field("current_len", &self.len()) + .field( + "context_memory", + &crate::primitives::hex::encode(self.context_memory()), + ) + .finish_non_exhaustive() + } +} + +impl Default for SharedMemory { + #[inline] + fn default() -> Self { + Self::new() + } +} + +impl SharedMemory { + /// Creates a new memory instance that can be shared between calls. + /// + /// The default initial capacity is 4KiB. + #[inline] + pub fn new() -> Self { + Self::with_capacity(4 * 1024) // from evmone + } + + /// Creates a new memory instance that can be shared between calls with the given `capacity`. + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + Self { + buffer: Vec::with_capacity(capacity), + checkpoints: Vec::with_capacity(32), + last_checkpoint: 0, + #[cfg(feature = "memory_limit")] + memory_limit: u64::MAX, + } + } + + /// Creates a new memory instance that can be shared between calls, + /// with `memory_limit` as upper bound for allocation size. + /// + /// The default initial capacity is 4KiB. + #[cfg(feature = "memory_limit")] + #[inline] + pub fn new_with_memory_limit(memory_limit: u64) -> Self { + Self { + memory_limit, + ..Self::new() + } + } + + /// Returns `true` if the `new_size` for the current context memory will + /// make the shared buffer length exceed the `memory_limit`. + #[cfg(feature = "memory_limit")] + #[inline] + pub fn limit_reached(&self, new_size: usize) -> bool { + (self.last_checkpoint + new_size) as u64 > self.memory_limit + } + + /// Prepares the shared memory for a new context. + #[inline] + pub fn new_context(&mut self) { + let new_checkpoint = self.buffer.len(); + self.checkpoints.push(new_checkpoint); + self.last_checkpoint = new_checkpoint; + } + + /// Prepares the shared memory for returning to the previous context. + #[inline] + pub fn free_context(&mut self) { + if let Some(old_checkpoint) = self.checkpoints.pop() { + self.last_checkpoint = self.checkpoints.last().cloned().unwrap_or_default(); + // SAFETY: buffer length is less than or equal `old_checkpoint` + unsafe { self.buffer.set_len(old_checkpoint) }; + } + } + + /// Returns the length of the current memory range. + #[inline] + pub fn len(&self) -> usize { + self.buffer.len() - self.last_checkpoint + } + + /// Returns `true` if the current memory range is empty. + #[inline] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns the gas cost for the current memory expansion. + #[inline] + pub fn current_expansion_cost(&self) -> u64 { + crate::gas::memory_gas_for_len(self.len()) + } + + /// Resizes the memory in-place so that `len` is equal to `new_len`. + #[inline] + pub fn resize(&mut self, new_size: usize) { + self.buffer.resize(self.last_checkpoint + new_size, 0); + } + + /// Returns a byte slice of the memory region at the given offset. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn slice(&self, offset: usize, size: usize) -> &[u8] { + self.slice_range(offset..offset + size) + } + + /// Returns a byte slice of the memory region at the given offset. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn slice_range(&self, range @ Range { start, end }: Range) -> &[u8] { + match self.context_memory().get(range) { + Some(slice) => slice, + None => debug_unreachable!("slice OOB: {start}..{end}; len: {}", self.len()), + } + } + + /// Returns a byte slice of the memory region at the given offset. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn slice_mut(&mut self, offset: usize, size: usize) -> &mut [u8] { + let end = offset + size; + match self.context_memory_mut().get_mut(offset..end) { + Some(slice) => slice, + None => debug_unreachable!("slice OOB: {offset}..{end}"), + } + } + + /// Returns the byte at the given offset. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + pub fn get_byte(&self, offset: usize) -> u8 { + self.slice(offset, 1)[0] + } + + /// Returns a 32-byte slice of the memory region at the given offset. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + pub fn get_word(&self, offset: usize) -> B256 { + self.slice(offset, 32).try_into().unwrap() + } + + /// Returns a U256 of the memory region at the given offset. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + pub fn get_u256(&self, offset: usize) -> U256 { + self.get_word(offset).into() + } + + /// Sets the `byte` at the given `index`. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn set_byte(&mut self, offset: usize, byte: u8) { + self.set(offset, &[byte]); + } + + /// Sets the given 32-byte `value` to the memory region at the given `offset`. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn set_word(&mut self, offset: usize, value: &B256) { + self.set(offset, &value[..]); + } + + /// Sets the given U256 `value` to the memory region at the given `offset`. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn set_u256(&mut self, offset: usize, value: U256) { + self.set(offset, &value.to_be_bytes::<32>()); + } + + /// Set memory region at given `offset`. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn set(&mut self, offset: usize, value: &[u8]) { + if !value.is_empty() { + self.slice_mut(offset, value.len()).copy_from_slice(value); + } + } + + /// Set memory from data. Our memory offset+len is expected to be correct but we + /// are doing bound checks on data/data_offeset/len and zeroing parts that is not copied. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn set_data(&mut self, memory_offset: usize, data_offset: usize, len: usize, data: &[u8]) { + if data_offset >= data.len() { + // nullify all memory slots + self.slice_mut(memory_offset, len).fill(0); + return; + } + let data_end = min(data_offset + len, data.len()); + let data_len = data_end - data_offset; + debug_assert!(data_offset < data.len() && data_end <= data.len()); + let data = unsafe { data.get_unchecked(data_offset..data_end) }; + self.slice_mut(memory_offset, data_len) + .copy_from_slice(data); + + // nullify rest of memory slots + // SAFETY: Memory is assumed to be valid, and it is commented where this assumption is made. + self.slice_mut(memory_offset + data_len, len - data_len) + .fill(0); + } + + /// Copies elements from one part of the memory to another part of itself. + /// + /// # Panics + /// + /// Panics on out of bounds. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn copy(&mut self, dst: usize, src: usize, len: usize) { + self.context_memory_mut().copy_within(src..src + len, dst); + } + + /// Returns a reference to the memory of the current context, the active memory. + #[inline] + pub fn context_memory(&self) -> &[u8] { + // SAFETY: access bounded by buffer length + unsafe { + self.buffer + .get_unchecked(self.last_checkpoint..self.buffer.len()) + } + } + + /// Returns a mutable reference to the memory of the current context. + #[inline] + pub fn context_memory_mut(&mut self) -> &mut [u8] { + let buf_len = self.buffer.len(); + // SAFETY: access bounded by buffer length + unsafe { self.buffer.get_unchecked_mut(self.last_checkpoint..buf_len) } + } +} + +/// Returns number of words what would fit to provided number of bytes, +/// i.e. it rounds up the number bytes to number of words. +#[inline] +pub const fn num_words(len: u64) -> u64 { + len.saturating_add(31) / 32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_num_words() { + assert_eq!(num_words(0), 0); + assert_eq!(num_words(1), 1); + assert_eq!(num_words(31), 1); + assert_eq!(num_words(32), 1); + assert_eq!(num_words(33), 2); + assert_eq!(num_words(63), 2); + assert_eq!(num_words(64), 2); + assert_eq!(num_words(65), 3); + assert_eq!(num_words(u64::MAX), u64::MAX / 32); + } + + #[test] + fn new_free_context() { + let mut shared_memory = SharedMemory::new(); + shared_memory.new_context(); + + assert_eq!(shared_memory.buffer.len(), 0); + assert_eq!(shared_memory.checkpoints.len(), 1); + assert_eq!(shared_memory.last_checkpoint, 0); + + unsafe { shared_memory.buffer.set_len(32) }; + assert_eq!(shared_memory.len(), 32); + shared_memory.new_context(); + + assert_eq!(shared_memory.buffer.len(), 32); + assert_eq!(shared_memory.checkpoints.len(), 2); + assert_eq!(shared_memory.last_checkpoint, 32); + assert_eq!(shared_memory.len(), 0); + + unsafe { shared_memory.buffer.set_len(96) }; + assert_eq!(shared_memory.len(), 64); + shared_memory.new_context(); + + assert_eq!(shared_memory.buffer.len(), 96); + assert_eq!(shared_memory.checkpoints.len(), 3); + assert_eq!(shared_memory.last_checkpoint, 96); + assert_eq!(shared_memory.len(), 0); + + // free contexts + shared_memory.free_context(); + assert_eq!(shared_memory.buffer.len(), 96); + assert_eq!(shared_memory.checkpoints.len(), 2); + assert_eq!(shared_memory.last_checkpoint, 32); + assert_eq!(shared_memory.len(), 64); + + shared_memory.free_context(); + assert_eq!(shared_memory.buffer.len(), 32); + assert_eq!(shared_memory.checkpoints.len(), 1); + assert_eq!(shared_memory.last_checkpoint, 0); + assert_eq!(shared_memory.len(), 32); + + shared_memory.free_context(); + assert_eq!(shared_memory.buffer.len(), 0); + assert_eq!(shared_memory.checkpoints.len(), 0); + assert_eq!(shared_memory.last_checkpoint, 0); + assert_eq!(shared_memory.len(), 0); + } + + #[test] + fn resize() { + let mut shared_memory = SharedMemory::new(); + shared_memory.new_context(); + + shared_memory.resize(32); + assert_eq!(shared_memory.buffer.len(), 32); + assert_eq!(shared_memory.len(), 32); + assert_eq!(shared_memory.buffer.get(0..32), Some(&[0_u8; 32] as &[u8])); + + shared_memory.new_context(); + shared_memory.resize(96); + assert_eq!(shared_memory.buffer.len(), 128); + assert_eq!(shared_memory.len(), 96); + assert_eq!( + shared_memory.buffer.get(32..128), + Some(&[0_u8; 96] as &[u8]) + ); + + shared_memory.free_context(); + shared_memory.resize(64); + assert_eq!(shared_memory.buffer.len(), 64); + assert_eq!(shared_memory.len(), 64); + assert_eq!(shared_memory.buffer.get(0..64), Some(&[0_u8; 64] as &[u8])); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/stack.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/stack.md new file mode 100644 index 00000000..9fa19fdb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter/stack.md @@ -0,0 +1,453 @@ +# ๐Ÿฆ€ stack.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter/stack.rs) + +```rust +use crate::{ + primitives::{B256, U256}, + InstructionResult, +}; +use core::{fmt, ptr}; +use std::vec::Vec; + +/// EVM interpreter stack limit. +pub const STACK_LIMIT: usize = 1024; + +/// EVM stack with [STACK_LIMIT] capacity of words. +#[derive(Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +pub struct Stack { + /// The underlying data of the stack. + data: Vec, +} + +impl fmt::Display for Stack { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("[")?; + for (i, x) in self.data.iter().enumerate() { + if i > 0 { + f.write_str(", ")?; + } + write!(f, "{x}")?; + } + f.write_str("]") + } +} + +impl Default for Stack { + #[inline] + fn default() -> Self { + Self::new() + } +} + +impl Stack { + /// Instantiate a new stack with the [default stack limit][STACK_LIMIT]. + #[inline] + pub fn new() -> Self { + Self { + // SAFETY: expansion functions assume that capacity is `STACK_LIMIT`. + data: Vec::with_capacity(STACK_LIMIT), + } + } + + /// Returns the length of the stack in words. + #[inline] + pub fn len(&self) -> usize { + self.data.len() + } + + /// Returns whether the stack is empty. + #[inline] + pub fn is_empty(&self) -> bool { + self.data.is_empty() + } + + /// Returns a reference to the underlying data buffer. + #[inline] + pub fn data(&self) -> &Vec { + &self.data + } + + /// Returns a mutable reference to the underlying data buffer. + #[inline] + pub fn data_mut(&mut self) -> &mut Vec { + &mut self.data + } + + /// Consumes the stack and returns the underlying data buffer. + #[inline] + pub fn into_data(self) -> Vec { + self.data + } + + /// Removes the topmost element from the stack and returns it, or `StackUnderflow` if it is + /// empty. + #[inline] + pub fn pop(&mut self) -> Result { + self.data.pop().ok_or(InstructionResult::StackUnderflow) + } + + /// Removes the topmost element from the stack and returns it. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop_unsafe(&mut self) -> U256 { + self.data.pop().unwrap_unchecked() + } + + /// Peeks the top of the stack. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn top_unsafe(&mut self) -> &mut U256 { + let len = self.data.len(); + self.data.get_unchecked_mut(len - 1) + } + + /// Pop the topmost value, returning the value and the new topmost value. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop_top_unsafe(&mut self) -> (U256, &mut U256) { + let pop = self.pop_unsafe(); + let top = self.top_unsafe(); + (pop, top) + } + + /// Pops 2 values from the stack. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop2_unsafe(&mut self) -> (U256, U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + (pop1, pop2) + } + + /// Pops 2 values from the stack and returns them, in addition to the new topmost value. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop2_top_unsafe(&mut self) -> (U256, U256, &mut U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + let top = self.top_unsafe(); + + (pop1, pop2, top) + } + + /// Pops 3 values from the stack. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop3_unsafe(&mut self) -> (U256, U256, U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + let pop3 = self.pop_unsafe(); + + (pop1, pop2, pop3) + } + + /// Pops 4 values from the stack. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop4_unsafe(&mut self) -> (U256, U256, U256, U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + let pop3 = self.pop_unsafe(); + let pop4 = self.pop_unsafe(); + + (pop1, pop2, pop3, pop4) + } + + /// Pops 5 values from the stack. + /// + /// # Safety + /// + /// The caller is responsible for checking the length of the stack. + #[inline] + pub unsafe fn pop5_unsafe(&mut self) -> (U256, U256, U256, U256, U256) { + let pop1 = self.pop_unsafe(); + let pop2 = self.pop_unsafe(); + let pop3 = self.pop_unsafe(); + let pop4 = self.pop_unsafe(); + let pop5 = self.pop_unsafe(); + + (pop1, pop2, pop3, pop4, pop5) + } + + /// Push a new value into the stack. If it will exceed the stack limit, + /// returns `StackOverflow` error and leaves the stack unchanged. + #[inline] + pub fn push_b256(&mut self, value: B256) -> Result<(), InstructionResult> { + self.push(value.into()) + } + + /// Push a new value onto the stack. + /// + /// If it will exceed the stack limit, returns `StackOverflow` error and leaves the stack + /// unchanged. + #[inline] + pub fn push(&mut self, value: U256) -> Result<(), InstructionResult> { + // Allows the compiler to optimize out the `Vec::push` capacity check. + assume!(self.data.capacity() == STACK_LIMIT); + if self.data.len() == STACK_LIMIT { + return Err(InstructionResult::StackOverflow); + } + self.data.push(value); + Ok(()) + } + + /// Peek a value at given index for the stack, where the top of + /// the stack is at index `0`. If the index is too large, + /// `StackError::Underflow` is returned. + #[inline] + pub fn peek(&self, no_from_top: usize) -> Result { + if self.data.len() > no_from_top { + Ok(self.data[self.data.len() - no_from_top - 1]) + } else { + Err(InstructionResult::StackUnderflow) + } + } + + /// Duplicates the `N`th value from the top of the stack. + /// + /// # Panics + /// + /// Panics if `n` is 0. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn dup(&mut self, n: usize) -> Result<(), InstructionResult> { + assume!(n > 0, "attempted to dup 0"); + let len = self.data.len(); + if len < n { + Err(InstructionResult::StackUnderflow) + } else if len + 1 > STACK_LIMIT { + Err(InstructionResult::StackOverflow) + } else { + // SAFETY: check for out of bounds is done above and it makes this safe to do. + unsafe { + let ptr = self.data.as_mut_ptr().add(len); + ptr::copy_nonoverlapping(ptr.sub(n), ptr, 1); + self.data.set_len(len + 1); + } + Ok(()) + } + } + + /// Swaps the topmost value with the `N`th value from the top. + /// + /// # Panics + /// + /// Panics if `n` is 0. + #[inline(always)] + #[cfg_attr(debug_assertions, track_caller)] + pub fn swap(&mut self, n: usize) -> Result<(), InstructionResult> { + self.exchange(0, n) + } + + /// Exchange two values on the stack. + /// + /// `n` is the first index, and the second index is calculated as `n + m`. + /// + /// # Panics + /// + /// Panics if `m` is zero. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + pub fn exchange(&mut self, n: usize, m: usize) -> Result<(), InstructionResult> { + assume!(m > 0, "overlapping exchange"); + let len = self.data.len(); + let n_m_index = n + m; + if n_m_index >= len { + return Err(InstructionResult::StackUnderflow); + } + // SAFETY: `n` and `n_m` are checked to be within bounds, and they don't overlap. + unsafe { + // NOTE: `ptr::swap_nonoverlapping` is more efficient than `slice::swap` or `ptr::swap` + // because it operates under the assumption that the pointers do not overlap, + // eliminating an intemediate copy, + // which is a condition we know to be true in this context. + let top = self.data.as_mut_ptr().add(len - 1); + core::ptr::swap_nonoverlapping(top.sub(n), top.sub(n_m_index), 1); + } + Ok(()) + } + + /// Pushes an arbitrary length slice of bytes onto the stack, padding the last word with zeros + /// if necessary. + #[inline] + pub fn push_slice(&mut self, slice: &[u8]) -> Result<(), InstructionResult> { + if slice.is_empty() { + return Ok(()); + } + + let n_words = (slice.len() + 31) / 32; + let new_len = self.data.len() + n_words; + if new_len > STACK_LIMIT { + return Err(InstructionResult::StackOverflow); + } + + // SAFETY: length checked above. + unsafe { + let dst = self.data.as_mut_ptr().add(self.data.len()).cast::(); + self.data.set_len(new_len); + + let mut i = 0; + + // write full words + let words = slice.chunks_exact(32); + let partial_last_word = words.remainder(); + for word in words { + // Note: we unroll `U256::from_be_bytes` here to write directly into the buffer, + // instead of creating a 32 byte array on the stack and then copying it over. + for l in word.rchunks_exact(8) { + dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap())); + i += 1; + } + } + + if partial_last_word.is_empty() { + return Ok(()); + } + + // write limbs of partial last word + let limbs = partial_last_word.rchunks_exact(8); + let partial_last_limb = limbs.remainder(); + for l in limbs { + dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap())); + i += 1; + } + + // write partial last limb by padding with zeros + if !partial_last_limb.is_empty() { + let mut tmp = [0u8; 8]; + tmp[8 - partial_last_limb.len()..].copy_from_slice(partial_last_limb); + dst.add(i).write(u64::from_be_bytes(tmp)); + i += 1; + } + + debug_assert_eq!((i + 3) / 4, n_words, "wrote too much"); + + // zero out upper bytes of last word + let m = i % 4; // 32 / 8 + if m != 0 { + dst.add(i).write_bytes(0, 4 - m); + } + } + + Ok(()) + } + + /// Set a value at given index for the stack, where the top of the + /// stack is at index `0`. If the index is too large, + /// `StackError::Underflow` is returned. + #[inline] + pub fn set(&mut self, no_from_top: usize, val: U256) -> Result<(), InstructionResult> { + if self.data.len() > no_from_top { + let len = self.data.len(); + self.data[len - no_from_top - 1] = val; + Ok(()) + } else { + Err(InstructionResult::StackUnderflow) + } + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for Stack { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let mut data = Vec::::deserialize(deserializer)?; + if data.len() > STACK_LIMIT { + return Err(serde::de::Error::custom(std::format!( + "stack size exceeds limit: {} > {}", + data.len(), + STACK_LIMIT + ))); + } + data.reserve(STACK_LIMIT - data.len()); + Ok(Self { data }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn run(f: impl FnOnce(&mut Stack)) { + let mut stack = Stack::new(); + // fill capacity with non-zero values + unsafe { + stack.data.set_len(STACK_LIMIT); + stack.data.fill(U256::MAX); + stack.data.set_len(0); + } + f(&mut stack); + } + + #[test] + fn push_slices() { + // no-op + run(|stack| { + stack.push_slice(b"").unwrap(); + assert_eq!(stack.data, []); + }); + + // one word + run(|stack| { + stack.push_slice(&[42]).unwrap(); + assert_eq!(stack.data, [U256::from(42)]); + }); + + let n = 0x1111_2222_3333_4444_5555_6666_7777_8888_u128; + run(|stack| { + stack.push_slice(&n.to_be_bytes()).unwrap(); + assert_eq!(stack.data, [U256::from(n)]); + }); + + // more than one word + run(|stack| { + let b = [U256::from(n).to_be_bytes::<32>(); 2].concat(); + stack.push_slice(&b).unwrap(); + assert_eq!(stack.data, [U256::from(n); 2]); + }); + + run(|stack| { + let b = [&[0; 32][..], &[42u8]].concat(); + stack.push_slice(&b).unwrap(); + assert_eq!(stack.data, [U256::ZERO, U256::from(42)]); + }); + + run(|stack| { + let b = [&[0; 32][..], &n.to_be_bytes()].concat(); + stack.push_slice(&b).unwrap(); + assert_eq!(stack.data, [U256::ZERO, U256::from(n)]); + }); + + run(|stack| { + let b = [&[0; 64][..], &n.to_be_bytes()].concat(); + stack.push_slice(&b).unwrap(); + assert_eq!(stack.data, [U256::ZERO, U256::ZERO, U256::from(n)]); + }); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action.md new file mode 100644 index 00000000..1c59fb86 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action.md @@ -0,0 +1,74 @@ +# ๐Ÿฆ€ interpreter_action.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter_action.rs) + +```rust +mod call_inputs; +mod call_outcome; +mod create_inputs; +mod create_outcome; +mod eof_create_inputs; +mod eof_create_outcome; + +pub use call_inputs::{CallInputs, CallScheme, CallValue}; +pub use call_outcome::CallOutcome; +pub use create_inputs::{CreateInputs, CreateScheme}; +pub use create_outcome::CreateOutcome; +pub use eof_create_inputs::EOFCreateInput; +pub use eof_create_outcome::EOFCreateOutcome; + +use crate::InterpreterResult; +use std::boxed::Box; + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum InterpreterAction { + /// CALL, CALLCODE, DELEGATECALL, STATICCALL + /// or EOF EXT instuction called. + Call { inputs: Box }, + /// CREATE or CREATE2 instruction called. + Create { inputs: Box }, + /// EOF CREATE instruction called. + EOFCreate { inputs: Box }, + /// Interpreter finished execution. + Return { result: InterpreterResult }, + /// No action + #[default] + None, +} + +impl InterpreterAction { + /// Returns true if action is call. + pub fn is_call(&self) -> bool { + matches!(self, InterpreterAction::Call { .. }) + } + + /// Returns true if action is create. + pub fn is_create(&self) -> bool { + matches!(self, InterpreterAction::Create { .. }) + } + + /// Returns true if action is return. + pub fn is_return(&self) -> bool { + matches!(self, InterpreterAction::Return { .. }) + } + + /// Returns true if action is none. + pub fn is_none(&self) -> bool { + matches!(self, InterpreterAction::None) + } + + /// Returns true if action is some. + pub fn is_some(&self) -> bool { + !self.is_none() + } + + /// Returns result if action is return. + pub fn into_result_return(self) -> Option { + match self { + InterpreterAction::Return { result } => Some(result), + _ => None, + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/call_inputs.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/call_inputs.md new file mode 100644 index 00000000..42bf269b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/call_inputs.md @@ -0,0 +1,198 @@ +# ๐Ÿฆ€ call_inputs.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter_action/call_inputs.rs) + +```rust +use crate::primitives::{Address, Bytes, TransactTo, TxEnv, U256}; +use core::ops::Range; +use std::boxed::Box; + +/// Inputs for a call. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CallInputs { + /// The call data of the call. + pub input: Bytes, + /// The return memory offset where the output of the call is written. + /// + /// In EOF, this range is invalid as EOF calls do not write output to memory. + pub return_memory_offset: Range, + /// The gas limit of the call. + pub gas_limit: u64, + /// The account address of bytecode that is going to be executed. + /// + /// Previously `context.code_address`. + pub bytecode_address: Address, + /// Target address, this account storage is going to be modified. + /// + /// Previously `context.address`. + pub target_address: Address, + /// This caller is invoking the call. + /// + /// Previously `context.caller`. + pub caller: Address, + /// Call value. + /// + /// NOTE: This value may not necessarily be transferred from caller to callee, see [`CallValue`]. + /// + /// Previously `transfer.value` or `context.apparent_value`. + pub value: CallValue, + /// The call scheme. + /// + /// Previously `context.scheme`. + pub scheme: CallScheme, + /// Whether the call is a static call, or is initiated inside a static call. + pub is_static: bool, + /// Whether the call is initiated from EOF bytecode. + pub is_eof: bool, +} + +impl CallInputs { + /// Creates new call inputs. + /// + /// Returns `None` if the transaction is not a call. + pub fn new(tx_env: &TxEnv, gas_limit: u64) -> Option { + let TransactTo::Call(target_address) = tx_env.transact_to else { + return None; + }; + Some(CallInputs { + input: tx_env.data.clone(), + gas_limit, + target_address, + bytecode_address: target_address, + caller: tx_env.caller, + value: CallValue::Transfer(tx_env.value), + scheme: CallScheme::Call, + is_static: false, + is_eof: false, + return_memory_offset: 0..0, + }) + } + + /// Creates new boxed call inputs. + /// + /// Returns `None` if the transaction is not a call. + pub fn new_boxed(tx_env: &TxEnv, gas_limit: u64) -> Option> { + Self::new(tx_env, gas_limit).map(Box::new) + } + + /// Returns `true` if the call will transfer a non-zero value. + #[inline] + pub fn transfers_value(&self) -> bool { + self.value.transfer().is_some_and(|x| x > U256::ZERO) + } + + /// Returns the transfer value. + /// + /// This is the value that is transferred from caller to callee, see [`CallValue`]. + #[inline] + pub const fn transfer_value(&self) -> Option { + self.value.transfer() + } + + /// Returns the **apparent** call value. + /// + /// This value is not actually transferred, see [`CallValue`]. + #[inline] + pub const fn apparent_value(&self) -> Option { + self.value.apparent() + } + + /// Returns the address of the transfer source account. + /// + /// This is only meaningful if `transfers_value` is `true`. + #[inline] + pub const fn transfer_from(&self) -> Address { + self.caller + } + + /// Returns the address of the transfer target account. + /// + /// This is only meaningful if `transfers_value` is `true`. + #[inline] + pub const fn transfer_to(&self) -> Address { + self.target_address + } + + /// Returns the call value, regardless of the transfer value type. + /// + /// NOTE: this value may not necessarily be transferred from caller to callee, see [`CallValue`]. + #[inline] + pub const fn call_value(&self) -> U256 { + self.value.get() + } +} + +/// Call scheme. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum CallScheme { + /// `CALL`. + Call, + /// `CALLCODE` + CallCode, + /// `DELEGATECALL` + DelegateCall, + /// `STATICCALL` + StaticCall, +} + +/// Call value. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum CallValue { + /// Concrete value, transferred from caller to callee at the end of the transaction. + Transfer(U256), + /// Apparent value, that is **not** actually transferred. + /// + /// Set when in a `DELEGATECALL` call type, and used by the `CALLVALUE` opcode. + Apparent(U256), +} + +impl Default for CallValue { + #[inline] + fn default() -> Self { + CallValue::Transfer(U256::ZERO) + } +} + +impl CallValue { + /// Returns the call value, regardless of the type. + #[inline] + pub const fn get(&self) -> U256 { + match *self { + Self::Transfer(value) | Self::Apparent(value) => value, + } + } + + /// Returns the transferred value, if any. + #[inline] + pub const fn transfer(&self) -> Option { + match *self { + Self::Transfer(transfer) => Some(transfer), + Self::Apparent(_) => None, + } + } + + /// Returns whether the call value will be transferred. + #[inline] + pub const fn is_transfer(&self) -> bool { + matches!(self, Self::Transfer(_)) + } + + /// Returns the apparent value, if any. + #[inline] + pub const fn apparent(&self) -> Option { + match *self { + Self::Transfer(_) => None, + Self::Apparent(apparent) => Some(apparent), + } + } + + /// Returns whether the call value is apparent, and not actually transferred. + #[inline] + pub const fn is_apparent(&self) -> bool { + matches!(self, Self::Apparent(_)) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/call_outcome.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/call_outcome.md new file mode 100644 index 00000000..3bd9d51a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/call_outcome.md @@ -0,0 +1,97 @@ +# ๐Ÿฆ€ call_outcome.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter_action/call_outcome.rs) + +```rust +use crate::{Gas, InstructionResult, InterpreterResult}; +use core::ops::Range; +use revm_primitives::Bytes; + +/// Represents the outcome of a call operation in a virtual machine. +/// +/// This struct encapsulates the result of executing an instruction by an interpreter, including +/// the result itself, gas usage information, and the memory offset where output data is stored. +/// +/// # Fields +/// +/// * `result` - The result of the interpreter's execution, including output data and gas usage. +/// * `memory_offset` - The range in memory where the output data is located. +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CallOutcome { + pub result: InterpreterResult, + pub memory_offset: Range, +} + +impl CallOutcome { + /// Constructs a new `CallOutcome`. + /// + /// Creates an instance of `CallOutcome` with the given interpreter result and memory offset. + /// + /// # Arguments + /// + /// * `result` - The result of the interpreter's execution. + /// * `memory_offset` - The range in memory indicating where the output data is stored. + pub fn new(result: InterpreterResult, memory_offset: Range) -> Self { + Self { + result, + memory_offset, + } + } + + /// Returns a reference to the instruction result. + /// + /// Provides access to the result of the executed instruction. + /// + /// # Returns + /// + /// A reference to the `InstructionResult`. + pub fn instruction_result(&self) -> &InstructionResult { + &self.result.result + } + + /// Returns the gas usage information. + /// + /// Provides access to the gas usage details of the executed instruction. + /// + /// # Returns + /// + /// An instance of `Gas` representing the gas usage. + pub fn gas(&self) -> Gas { + self.result.gas + } + + /// Returns a reference to the output data. + /// + /// Provides access to the output data generated by the executed instruction. + /// + /// # Returns + /// + /// A reference to the output data as `Bytes`. + pub fn output(&self) -> &Bytes { + &self.result.output + } + + /// Returns the start position of the memory offset. + /// + /// Provides the starting index of the memory range where the output data is stored. + /// + /// # Returns + /// + /// The starting index of the memory offset as `usize`. + pub fn memory_start(&self) -> usize { + self.memory_offset.start + } + + /// Returns the length of the memory range. + /// + /// Provides the length of the memory range where the output data is stored. + /// + /// # Returns + /// + /// The length of the memory range as `usize`. + pub fn memory_length(&self) -> usize { + self.memory_offset.len() + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/create_inputs.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/create_inputs.md new file mode 100644 index 00000000..8823bd01 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/create_inputs.md @@ -0,0 +1,57 @@ +# ๐Ÿฆ€ create_inputs.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter_action/create_inputs.rs) + +```rust +pub use crate::primitives::CreateScheme; +use crate::primitives::{Address, Bytes, TransactTo, TxEnv, U256}; +use std::boxed::Box; + +/// Inputs for a create call. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateInputs { + /// Caller address of the EVM. + pub caller: Address, + /// The create scheme. + pub scheme: CreateScheme, + /// The value to transfer. + pub value: U256, + /// The init code of the contract. + pub init_code: Bytes, + /// The gas limit of the call. + pub gas_limit: u64, +} + +impl CreateInputs { + /// Creates new create inputs. + pub fn new(tx_env: &TxEnv, gas_limit: u64) -> Option { + let TransactTo::Create = tx_env.transact_to else { + return None; + }; + + Some(CreateInputs { + caller: tx_env.caller, + scheme: CreateScheme::Create, + value: tx_env.value, + init_code: tx_env.data.clone(), + gas_limit, + }) + } + + /// Returns boxed create inputs. + pub fn new_boxed(tx_env: &TxEnv, gas_limit: u64) -> Option> { + Self::new(tx_env, gas_limit).map(Box::new) + } + + /// Returns the address that this create call will create. + pub fn created_address(&self, nonce: u64) -> Address { + match self.scheme { + CreateScheme::Create => self.caller.create(nonce), + CreateScheme::Create2 { salt } => self + .caller + .create2_from_code(salt.to_be_bytes(), &self.init_code), + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/create_outcome.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/create_outcome.md new file mode 100644 index 00000000..9a403044 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/create_outcome.md @@ -0,0 +1,76 @@ +# ๐Ÿฆ€ create_outcome.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter_action/create_outcome.rs) + +```rust +use crate::{Gas, InstructionResult, InterpreterResult}; +use revm_primitives::{Address, Bytes}; + +/// Represents the outcome of a create operation in an interpreter. +/// +/// This struct holds the result of the operation along with an optional address. +/// It provides methods to determine the next action based on the result of the operation. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateOutcome { + // The result of the interpreter operation. + pub result: InterpreterResult, + // An optional address associated with the create operation. + pub address: Option
, +} + +impl CreateOutcome { + /// Constructs a new `CreateOutcome`. + /// + /// # Arguments + /// + /// * `result` - An `InterpreterResult` representing the result of the interpreter operation. + /// * `address` - An optional `Address` associated with the create operation. + /// + /// # Returns + /// + /// A new `CreateOutcome` instance. + pub fn new(result: InterpreterResult, address: Option
) -> Self { + Self { result, address } + } + + /// Retrieves a reference to the `InstructionResult` from the `InterpreterResult`. + /// + /// This method provides access to the `InstructionResult` which represents the + /// outcome of the instruction execution. It encapsulates the result information + /// such as whether the instruction was executed successfully, resulted in a revert, + /// or encountered a fatal error. + /// + /// # Returns + /// + /// A reference to the `InstructionResult`. + pub fn instruction_result(&self) -> &InstructionResult { + &self.result.result + } + + /// Retrieves a reference to the output bytes from the `InterpreterResult`. + /// + /// This method returns the output of the interpreted operation. The output is + /// typically used when the operation successfully completes and returns data. + /// + /// # Returns + /// + /// A reference to the output `Bytes`. + pub fn output(&self) -> &Bytes { + &self.result.output + } + + /// Retrieves a reference to the `Gas` details from the `InterpreterResult`. + /// + /// This method provides access to the gas details of the operation, which includes + /// information about gas used, remaining, and refunded. It is essential for + /// understanding the gas consumption of the operation. + /// + /// # Returns + /// + /// A reference to the `Gas` details. + pub fn gas(&self) -> &Gas { + &self.result.gas + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/eof_create_inputs.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/eof_create_inputs.md new file mode 100644 index 00000000..ea339dd5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/eof_create_inputs.md @@ -0,0 +1,48 @@ +# ๐Ÿฆ€ eof_create_inputs.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter_action/eof_create_inputs.rs) + +```rust +use crate::primitives::{Address, Eof, U256}; +use core::ops::Range; + +/// Inputs for EOF create call. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct EOFCreateInput { + /// Caller of Eof Craate + pub caller: Address, + /// New contract address. + pub created_address: Address, + /// Values of ether transfered + pub value: U256, + /// Init eof code that is going to be executed. + pub eof_init_code: Eof, + /// Gas limit for the create call. + pub gas_limit: u64, + /// Return memory range. If EOF creation Reverts it can return the + /// the memory range. + pub return_memory_range: Range, +} + +impl EOFCreateInput { + /// Returns a new instance of EOFCreateInput. + pub fn new( + caller: Address, + created_address: Address, + value: U256, + eof_init_code: Eof, + gas_limit: u64, + return_memory_range: Range, + ) -> EOFCreateInput { + EOFCreateInput { + caller, + created_address, + value, + eof_init_code, + gas_limit, + return_memory_range, + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/eof_create_outcome.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/eof_create_outcome.md new file mode 100644 index 00000000..b77a8125 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/interpreter_action/eof_create_outcome.md @@ -0,0 +1,94 @@ +# ๐Ÿฆ€ eof_create_outcome.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/interpreter_action/eof_create_outcome.rs) + +```rust +use core::ops::Range; + +use crate::{Gas, InstructionResult, InterpreterResult}; +use revm_primitives::{Address, Bytes}; + +/// Represents the outcome of a create operation in an interpreter. +/// +/// This struct holds the result of the operation along with an optional address. +/// It provides methods to determine the next action based on the result of the operation. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct EOFCreateOutcome { + /// The result of the interpreter operation. + pub result: InterpreterResult, + /// An optional address associated with the create operation. + pub address: Address, + /// Return memory range. If EOF creation Reverts it can return bytes from the memory. + pub return_memory_range: Range, +} + +impl EOFCreateOutcome { + /// Constructs a new [`EOFCreateOutcome`]. + /// + /// # Arguments + /// + /// * `result` - An `InterpreterResult` representing the result of the interpreter operation. + /// * `address` - An optional `Address` associated with the create operation. + /// * `return_memory_range` - The memory range that Revert bytes are going to be written. + /// + /// # Returns + /// + /// A new [`EOFCreateOutcome`] instance. + pub fn new( + result: InterpreterResult, + address: Address, + return_memory_range: Range, + ) -> Self { + Self { + result, + address, + return_memory_range, + } + } + + /// Retrieves a reference to the [`InstructionResult`] from the [`InterpreterResult`]. + /// + /// This method provides access to the `InstructionResult` which represents the + /// outcome of the instruction execution. It encapsulates the result information + /// such as whether the instruction was executed successfully, resulted in a revert, + /// or encountered a fatal error. + /// + /// # Returns + /// + /// A reference to the `InstructionResult`. + pub fn instruction_result(&self) -> &InstructionResult { + &self.result.result + } + + /// Retrieves a reference to the output bytes from the `InterpreterResult`. + /// + /// This method returns the output of the interpreted operation. The output is + /// typically used when the operation successfully completes and returns data. + /// + /// # Returns + /// + /// A reference to the output `Bytes`. + pub fn output(&self) -> &Bytes { + &self.result.output + } + + /// Retrieves a reference to the `Gas` details from the `InterpreterResult`. + /// + /// This method provides access to the gas details of the operation, which includes + /// information about gas used, remaining, and refunded. It is essential for + /// understanding the gas consumption of the operation. + /// + /// # Returns + /// + /// A reference to the `Gas` details. + pub fn gas(&self) -> &Gas { + &self.result.gas + } + + /// Returns the memory range that Revert bytes are going to be written. + pub fn return_range(&self) -> Range { + self.return_memory_range.clone() + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/lib.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/lib.md new file mode 100644 index 00000000..0bfd6d8c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/lib.md @@ -0,0 +1,54 @@ +# ๐Ÿฆ€ lib.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/lib.rs) + +```rust +//! # revm-interpreter +//! +//! REVM Interpreter. +#![warn(rustdoc::all)] +#![warn(unreachable_pub, unused_crate_dependencies)] +#![deny(unused_must_use, rust_2018_idioms)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(not(feature = "std"))] +extern crate alloc as std; + +#[macro_use] +mod macros; + +// silence lint +#[cfg(test)] +use serde_json as _; + +#[cfg(test)] +use walkdir as _; + +mod function_stack; +pub mod gas; +mod host; +mod instruction_result; +pub mod instructions; +pub mod interpreter; +pub mod interpreter_action; +pub mod opcode; + +// Reexport primary types. +pub use function_stack::{FunctionReturnFrame, FunctionStack}; +pub use gas::Gas; +pub use host::{DummyHost, Host, LoadAccountResult, SStoreResult, SelfDestructResult}; +pub use instruction_result::*; +pub use interpreter::{ + analysis, num_words, Contract, Interpreter, InterpreterResult, SharedMemory, Stack, + EMPTY_SHARED_MEMORY, STACK_LIMIT, +}; +pub use interpreter_action::{ + CallInputs, CallOutcome, CallScheme, CallValue, CreateInputs, CreateOutcome, CreateScheme, + EOFCreateInput, EOFCreateOutcome, InterpreterAction, +}; +pub use opcode::{Instruction, OpCode, OPCODE_INFO_JUMPTABLE}; +pub use primitives::{MAX_CODE_SIZE, MAX_INITCODE_SIZE}; + +#[doc(hidden)] +pub use revm_primitives as primitives; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/macros.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/macros.md new file mode 100644 index 00000000..d7863653 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/macros.md @@ -0,0 +1,29 @@ +# ๐Ÿฆ€ macros.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/macros.rs) + +```rust +macro_rules! debug_unreachable { + ($($t:tt)*) => { + if cfg!(debug_assertions) { + unreachable!($($t)*); + } else { + unsafe { core::hint::unreachable_unchecked() }; + } + }; +} + +macro_rules! assume { + ($e:expr $(,)?) => { + if !$e { + debug_unreachable!(stringify!($e)); + } + }; + + ($e:expr, $($t:tt)+) => { + if !$e { + debug_unreachable!($($t)+); + } + }; +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/opcode.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/opcode.md new file mode 100644 index 00000000..7de93684 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/opcode.md @@ -0,0 +1,913 @@ +# ๐Ÿฆ€ opcode.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/opcode.rs) + +```rust +//! EVM opcode definitions and utilities. + +pub mod eof_printer; + +use crate::{instructions::*, primitives::Spec, Host, Interpreter}; +use core::{fmt, ptr::NonNull}; +use std::boxed::Box; + +/// EVM opcode function signature. +pub type Instruction = fn(&mut Interpreter, &mut H); + +/// Instruction table is list of instruction function pointers mapped to +/// 256 EVM opcodes. +pub type InstructionTable = [Instruction; 256]; + +/// EVM opcode function signature. +pub type BoxedInstruction<'a, H> = Box; + +/// A table of instructions. +pub type BoxedInstructionTable<'a, H> = [BoxedInstruction<'a, H>; 256]; + +/// Instruction set that contains plain instruction table that contains simple `fn` function pointer. +/// and Boxed `Fn` variant that contains `Box` function pointer that can be used with closured. +/// +/// Note that `Plain` variant gives us 10-20% faster Interpreter execution. +/// +/// Boxed variant can be used to wrap plain function pointer with closure. +pub enum InstructionTables<'a, H> { + Plain(InstructionTable), + Boxed(BoxedInstructionTable<'a, H>), +} + +impl InstructionTables<'_, H> { + /// Creates a plain instruction table for the given spec. + #[inline] + pub const fn new_plain() -> Self { + Self::Plain(make_instruction_table::()) + } +} + +impl<'a, H: Host + 'a> InstructionTables<'a, H> { + /// Inserts a boxed instruction into the table with the specified index. + /// + /// This will convert the table into the [BoxedInstructionTable] variant if it is currently a + /// plain instruction table, before inserting the instruction. + #[inline] + pub fn insert_boxed(&mut self, opcode: u8, instruction: BoxedInstruction<'a, H>) { + // first convert the table to boxed variant + self.convert_boxed(); + + // now we can insert the instruction + match self { + Self::Plain(_) => { + unreachable!("we already converted the table to boxed variant"); + } + Self::Boxed(table) => { + table[opcode as usize] = Box::new(instruction); + } + } + } + + /// Inserts the instruction into the table with the specified index. + #[inline] + pub fn insert(&mut self, opcode: u8, instruction: Instruction) { + match self { + Self::Plain(table) => { + table[opcode as usize] = instruction; + } + Self::Boxed(table) => { + table[opcode as usize] = Box::new(instruction); + } + } + } + + /// Converts the current instruction table to a boxed variant. If the table is already boxed, + /// this is a no-op. + #[inline] + pub fn convert_boxed(&mut self) { + match self { + Self::Plain(table) => { + *self = Self::Boxed(core::array::from_fn(|i| { + let instruction: BoxedInstruction<'a, H> = Box::new(table[i]); + instruction + })); + } + Self::Boxed(_) => {} + }; + } +} + +/// Make instruction table. +#[inline] +pub const fn make_instruction_table() -> InstructionTable { + // Force const-eval of the table creation, making this function trivial. + // TODO: Replace this with a `const {}` block once it is stable. + struct ConstTable { + _host: core::marker::PhantomData, + _spec: core::marker::PhantomData, + } + impl ConstTable { + const NEW: InstructionTable = { + let mut tables: InstructionTable = [control::unknown; 256]; + let mut i = 0; + while i < 256 { + tables[i] = instruction::(i as u8); + i += 1; + } + tables + }; + } + ConstTable::::NEW +} + +/// Make boxed instruction table that calls `outer` closure for every instruction. +#[inline] +pub fn make_boxed_instruction_table<'a, H, SPEC, FN>( + table: InstructionTable, + mut outer: FN, +) -> BoxedInstructionTable<'a, H> +where + H: Host, + SPEC: Spec + 'a, + FN: FnMut(Instruction) -> BoxedInstruction<'a, H>, +{ + core::array::from_fn(|i| outer(table[i])) +} + +/// An error indicating that an opcode is invalid. +#[derive(Debug, PartialEq, Eq)] +#[cfg(feature = "parse")] +pub struct OpCodeError(()); + +#[cfg(feature = "parse")] +impl fmt::Display for OpCodeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("invalid opcode") + } +} + +#[cfg(all(feature = "std", feature = "parse"))] +impl std::error::Error for OpCodeError {} + +/// An EVM opcode. +/// +/// This is always a valid opcode, as declared in the [`opcode`][self] module or the +/// [`OPCODE_INFO_JUMPTABLE`] constant. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +pub struct OpCode(u8); + +impl fmt::Display for OpCode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let n = self.get(); + if let Some(val) = OPCODE_INFO_JUMPTABLE[n as usize] { + f.write_str(val.name()) + } else { + write!(f, "UNKNOWN(0x{n:02X})") + } + } +} + +#[cfg(feature = "parse")] +impl core::str::FromStr for OpCode { + type Err = OpCodeError; + + #[inline] + fn from_str(s: &str) -> Result { + Self::parse(s).ok_or(OpCodeError(())) + } +} + +impl OpCode { + /// Instantiate a new opcode from a u8. + #[inline] + pub const fn new(opcode: u8) -> Option { + match OPCODE_INFO_JUMPTABLE[opcode as usize] { + Some(_) => Some(Self(opcode)), + None => None, + } + } + + /// Parses an opcode from a string. This is the inverse of [`as_str`](Self::as_str). + #[inline] + #[cfg(feature = "parse")] + pub fn parse(s: &str) -> Option { + NAME_TO_OPCODE.get(s).copied() + } + + /// Returns true if the opcode is a jump destination. + #[inline] + pub const fn is_jumpdest(&self) -> bool { + self.0 == JUMPDEST + } + + /// Takes a u8 and returns true if it is a jump destination. + #[inline] + pub const fn is_jumpdest_by_op(opcode: u8) -> bool { + if let Some(opcode) = Self::new(opcode) { + opcode.is_jumpdest() + } else { + false + } + } + + /// Returns true if the opcode is a legacy jump instruction. + #[inline] + pub const fn is_jump(self) -> bool { + self.0 == JUMP + } + + /// Takes a u8 and returns true if it is a jump instruction. + #[inline] + pub const fn is_jump_by_op(opcode: u8) -> bool { + if let Some(opcode) = Self::new(opcode) { + opcode.is_jump() + } else { + false + } + } + + /// Returns true if the opcode is a `PUSH` instruction. + #[inline] + pub const fn is_push(self) -> bool { + self.0 >= PUSH1 && self.0 <= PUSH32 + } + + /// Takes a u8 and returns true if it is a push instruction. + #[inline] + pub fn is_push_by_op(opcode: u8) -> bool { + if let Some(opcode) = Self::new(opcode) { + opcode.is_push() + } else { + false + } + } + + /// Instantiate a new opcode from a u8 without checking if it is valid. + /// + /// # Safety + /// + /// All code using `Opcode` values assume that they are valid opcodes, so providing an invalid + /// opcode may cause undefined behavior. + #[inline] + pub unsafe fn new_unchecked(opcode: u8) -> Self { + Self(opcode) + } + + /// Returns the opcode as a string. This is the inverse of [`parse`](Self::parse). + #[doc(alias = "name")] + #[inline] + pub const fn as_str(self) -> &'static str { + self.info().name() + } + + /// Returns the opcode name. + #[inline] + pub const fn name_by_op(opcode: u8) -> &'static str { + if let Some(opcode) = Self::new(opcode) { + opcode.as_str() + } else { + "Unknown" + } + } + + /// Returns the number of input stack elements. + #[inline] + pub const fn inputs(&self) -> u8 { + self.info().inputs() + } + + /// Returns the number of output stack elements. + #[inline] + pub const fn outputs(&self) -> u8 { + self.info().outputs() + } + + /// Calculates the difference between the number of input and output stack elements. + #[inline] + pub const fn io_diff(&self) -> i16 { + self.info().io_diff() + } + + /// Returns the opcode information for the given opcode. + #[inline] + pub const fn info_by_op(opcode: u8) -> Option { + if let Some(opcode) = Self::new(opcode) { + Some(opcode.info()) + } else { + None + } + } + + /// Returns the opcode information. + #[inline] + pub const fn info(&self) -> OpCodeInfo { + if let Some(t) = OPCODE_INFO_JUMPTABLE[self.0 as usize] { + t + } else { + panic!("opcode not found") + } + } + + /// Returns the number of both input and output stack elements. + /// + /// Can be slightly faster that calling `inputs` and `outputs` separately. + pub const fn input_output(&self) -> (u8, u8) { + let info = self.info(); + (info.inputs, info.outputs) + } + + /// Returns the opcode as a u8. + #[inline] + pub const fn get(self) -> u8 { + self.0 + } +} + +/// Information about opcode, such as name, and stack inputs and outputs. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct OpCodeInfo { + /// Invariant: `(name_ptr, name_len)` is a `&'static str`. It is a shorted variant of `str` as + /// the name length is always less than 256 characters. + name_ptr: NonNull, + name_len: u8, + /// Stack inputs. + inputs: u8, + /// Stack outputs. + outputs: u8, + /// Number of intermediate bytes. + /// + /// RJUMPV is a special case where the bytes len depends on bytecode value, + /// for RJUMV size will be set to one byte as it is the minimum immediate size. + immediate_size: u8, + /// Used by EOF verification. All not EOF opcodes are marked false. + not_eof: bool, + /// If the opcode stops execution. aka STOP, RETURN, .. + terminating: bool, +} + +impl fmt::Debug for OpCodeInfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OpCodeInfo") + .field("name", &self.name()) + .field("inputs", &self.inputs()) + .field("outputs", &self.outputs()) + .field("not_eof", &self.is_disabled_in_eof()) + .field("terminating", &self.is_terminating()) + .field("immediate_size", &self.immediate_size()) + .finish() + } +} + +impl OpCodeInfo { + /// Creates a new opcode info with the given name and default values. + pub const fn new(name: &'static str) -> Self { + assert!(name.len() < 256, "opcode name is too long"); + Self { + name_ptr: unsafe { NonNull::new_unchecked(name.as_ptr().cast_mut()) }, + name_len: name.len() as u8, + inputs: 0, + outputs: 0, + not_eof: false, + terminating: false, + immediate_size: 0, + } + } + + /// Returns the opcode name. + #[inline] + pub const fn name(&self) -> &'static str { + // SAFETY: `self.name_*` can only be initialized with a valid `&'static str`. + unsafe { + // TODO: Use `str::from_raw_parts` when it's stable. + let slice = core::slice::from_raw_parts(self.name_ptr.as_ptr(), self.name_len as usize); + core::str::from_utf8_unchecked(slice) + } + } + + /// Calculates the difference between the number of input and output stack elements. + #[inline] + pub const fn io_diff(&self) -> i16 { + self.outputs as i16 - self.inputs as i16 + } + + /// Returns the number of input stack elements. + #[inline] + pub const fn inputs(&self) -> u8 { + self.inputs + } + + /// Returns the number of output stack elements. + #[inline] + pub const fn outputs(&self) -> u8 { + self.outputs + } + + /// Returns whether this opcode is disabled in EOF bytecode. + #[inline] + pub const fn is_disabled_in_eof(&self) -> bool { + self.not_eof + } + + /// Returns whether this opcode terminates execution, e.g. `STOP`, `RETURN`, etc. + #[inline] + pub const fn is_terminating(&self) -> bool { + self.terminating + } + + /// Returns the size of the immediate value in bytes. + #[inline] + pub const fn immediate_size(&self) -> u8 { + self.immediate_size + } +} + +/// Sets the EOF flag to false. +#[inline] +pub const fn not_eof(mut op: OpCodeInfo) -> OpCodeInfo { + op.not_eof = true; + op +} + +/// Sets the immediate bytes number. +/// +/// RJUMPV is special case where the bytes len is depending on bytecode value, +/// for RJUMPV size will be set to one byte while minimum is two. +#[inline] +pub const fn immediate_size(mut op: OpCodeInfo, n: u8) -> OpCodeInfo { + op.immediate_size = n; + op +} + +/// Sets the terminating flag to true. +#[inline] +pub const fn terminating(mut op: OpCodeInfo) -> OpCodeInfo { + op.terminating = true; + op +} + +/// Sets the number of stack inputs and outputs. +#[inline] +pub const fn stack_io(mut op: OpCodeInfo, inputs: u8, outputs: u8) -> OpCodeInfo { + op.inputs = inputs; + op.outputs = outputs; + op +} + +/// Alias for the [`JUMPDEST`] opcode. +pub const NOP: u8 = JUMPDEST; + +/// Callback for creating a [`phf`] map with `stringify_with_cb`. +#[cfg(feature = "parse")] +macro_rules! phf_map_cb { + ($(#[doc = $s:literal] $id:ident)*) => { + phf::phf_map! { + $($s => OpCode::$id),* + } + }; +} + +/// Stringifies identifiers with `paste` so that they are available as literals. +/// This doesn't work with `stringify!` because it cannot be expanded inside of another macro. +#[cfg(feature = "parse")] +macro_rules! stringify_with_cb { + ($callback:ident; $($id:ident)*) => { paste::paste! { + $callback! { $(#[doc = "" $id ""] $id)* } + }}; +} + +macro_rules! opcodes { + ($($val:literal => $name:ident => $f:expr => $($modifier:ident $(( $($modifier_arg:expr),* ))?),*);* $(;)?) => { + // Constants for each opcode. This also takes care of duplicate names. + $( + #[doc = concat!("The `", stringify!($val), "` (\"", stringify!($name),"\") opcode.")] + pub const $name: u8 = $val; + )* + impl OpCode {$( + #[doc = concat!("The `", stringify!($val), "` (\"", stringify!($name),"\") opcode.")] + pub const $name: Self = Self($val); + )*} + + /// Maps each opcode to its info. + pub const OPCODE_INFO_JUMPTABLE: [Option; 256] = { + let mut map = [None; 256]; + let mut prev: u8 = 0; + $( + let val: u8 = $val; + assert!(val == 0 || val > prev, "opcodes must be sorted in ascending order"); + prev = val; + let info = OpCodeInfo::new(stringify!($name)); + $( + let info = $modifier(info, $($($modifier_arg),*)?); + )* + map[$val] = Some(info); + )* + let _ = prev; + map + }; + + /// Maps each name to its opcode. + #[cfg(feature = "parse")] + static NAME_TO_OPCODE: phf::Map<&'static str, OpCode> = stringify_with_cb! { phf_map_cb; $($name)* }; + + /// Returns the instruction function for the given opcode and spec. + pub const fn instruction(opcode: u8) -> Instruction { + match opcode { + $($name => $f,)* + _ => control::unknown, + } + } + }; +} + +// When adding new opcodes: +// 1. add the opcode to the list below; make sure it's sorted by opcode value +// 2. implement the opcode in the corresponding module; +// the function signature must be the exact same as the others +opcodes! { + 0x00 => STOP => control::stop => stack_io(0, 0), terminating; + + 0x01 => ADD => arithmetic::add => stack_io(2, 1); + 0x02 => MUL => arithmetic::mul => stack_io(2, 1); + 0x03 => SUB => arithmetic::sub => stack_io(2, 1); + 0x04 => DIV => arithmetic::div => stack_io(2, 1); + 0x05 => SDIV => arithmetic::sdiv => stack_io(2, 1); + 0x06 => MOD => arithmetic::rem => stack_io(2, 1); + 0x07 => SMOD => arithmetic::smod => stack_io(2, 1); + 0x08 => ADDMOD => arithmetic::addmod => stack_io(3, 1); + 0x09 => MULMOD => arithmetic::mulmod => stack_io(3, 1); + 0x0A => EXP => arithmetic::exp:: => stack_io(2, 1); + 0x0B => SIGNEXTEND => arithmetic::signextend => stack_io(2, 1); + // 0x0C + // 0x0D + // 0x0E + // 0x0F + 0x10 => LT => bitwise::lt => stack_io(2, 1); + 0x11 => GT => bitwise::gt => stack_io(2, 1); + 0x12 => SLT => bitwise::slt => stack_io(2, 1); + 0x13 => SGT => bitwise::sgt => stack_io(2, 1); + 0x14 => EQ => bitwise::eq => stack_io(2, 1); + 0x15 => ISZERO => bitwise::iszero => stack_io(1, 1); + 0x16 => AND => bitwise::bitand => stack_io(2, 1); + 0x17 => OR => bitwise::bitor => stack_io(2, 1); + 0x18 => XOR => bitwise::bitxor => stack_io(2, 1); + 0x19 => NOT => bitwise::not => stack_io(1, 1); + 0x1A => BYTE => bitwise::byte => stack_io(2, 1); + 0x1B => SHL => bitwise::shl:: => stack_io(2, 1); + 0x1C => SHR => bitwise::shr:: => stack_io(2, 1); + 0x1D => SAR => bitwise::sar:: => stack_io(2, 1); + // 0x1E + // 0x1F + 0x20 => KECCAK256 => system::keccak256 => stack_io(2, 1); + // 0x21 + // 0x22 + // 0x23 + // 0x24 + // 0x25 + // 0x26 + // 0x27 + // 0x28 + // 0x29 + // 0x2A + // 0x2B + // 0x2C + // 0x2D + // 0x2E + // 0x2F + 0x30 => ADDRESS => system::address => stack_io(0, 1); + 0x31 => BALANCE => host::balance:: => stack_io(1, 1); + 0x32 => ORIGIN => host_env::origin => stack_io(0, 1); + 0x33 => CALLER => system::caller => stack_io(0, 1); + 0x34 => CALLVALUE => system::callvalue => stack_io(0, 1); + 0x35 => CALLDATALOAD => system::calldataload => stack_io(1, 1); + 0x36 => CALLDATASIZE => system::calldatasize => stack_io(0, 1); + 0x37 => CALLDATACOPY => system::calldatacopy => stack_io(3, 0); + 0x38 => CODESIZE => system::codesize => stack_io(0, 1), not_eof; + 0x39 => CODECOPY => system::codecopy => stack_io(3, 0), not_eof; + + 0x3A => GASPRICE => host_env::gasprice => stack_io(0, 1); + 0x3B => EXTCODESIZE => host::extcodesize:: => stack_io(1, 1), not_eof; + 0x3C => EXTCODECOPY => host::extcodecopy:: => stack_io(4, 0), not_eof; + 0x3D => RETURNDATASIZE => system::returndatasize:: => stack_io(0, 1); + 0x3E => RETURNDATACOPY => system::returndatacopy:: => stack_io(3, 0); + 0x3F => EXTCODEHASH => host::extcodehash:: => stack_io(1, 1), not_eof; + 0x40 => BLOCKHASH => host::blockhash:: => stack_io(1, 1); + 0x41 => COINBASE => host_env::coinbase => stack_io(0, 1); + 0x42 => TIMESTAMP => host_env::timestamp => stack_io(0, 1); + 0x43 => NUMBER => host_env::block_number => stack_io(0, 1); + 0x44 => DIFFICULTY => host_env::difficulty:: => stack_io(0, 1); + 0x45 => GASLIMIT => host_env::gaslimit => stack_io(0, 1); + 0x46 => CHAINID => host_env::chainid:: => stack_io(0, 1); + 0x47 => SELFBALANCE => host::selfbalance:: => stack_io(0, 1); + 0x48 => BASEFEE => host_env::basefee:: => stack_io(0, 1); + 0x49 => BLOBHASH => host_env::blob_hash:: => stack_io(1, 1); + 0x4A => BLOBBASEFEE => host_env::blob_basefee:: => stack_io(0, 1); + // 0x4B + // 0x4C + // 0x4D + // 0x4E + // 0x4F + 0x50 => POP => stack::pop => stack_io(1, 0); + 0x51 => MLOAD => memory::mload => stack_io(1, 1); + 0x52 => MSTORE => memory::mstore => stack_io(2, 0); + 0x53 => MSTORE8 => memory::mstore8 => stack_io(2, 0); + 0x54 => SLOAD => host::sload:: => stack_io(1, 1); + 0x55 => SSTORE => host::sstore:: => stack_io(2, 0); + 0x56 => JUMP => control::jump => stack_io(1, 0), not_eof; + 0x57 => JUMPI => control::jumpi => stack_io(2, 0), not_eof; + 0x58 => PC => control::pc => stack_io(0, 1), not_eof; + 0x59 => MSIZE => memory::msize => stack_io(0, 1); + 0x5A => GAS => system::gas => stack_io(0, 1), not_eof; + 0x5B => JUMPDEST => control::jumpdest_or_nop => stack_io(0, 0); + 0x5C => TLOAD => host::tload:: => stack_io(1, 1); + 0x5D => TSTORE => host::tstore:: => stack_io(2, 0); + 0x5E => MCOPY => memory::mcopy:: => stack_io(3, 0); + + 0x5F => PUSH0 => stack::push0:: => stack_io(0, 1); + 0x60 => PUSH1 => stack::push::<1, H> => stack_io(0, 1), immediate_size(1); + 0x61 => PUSH2 => stack::push::<2, H> => stack_io(0, 1), immediate_size(2); + 0x62 => PUSH3 => stack::push::<3, H> => stack_io(0, 1), immediate_size(3); + 0x63 => PUSH4 => stack::push::<4, H> => stack_io(0, 1), immediate_size(4); + 0x64 => PUSH5 => stack::push::<5, H> => stack_io(0, 1), immediate_size(5); + 0x65 => PUSH6 => stack::push::<6, H> => stack_io(0, 1), immediate_size(6); + 0x66 => PUSH7 => stack::push::<7, H> => stack_io(0, 1), immediate_size(7); + 0x67 => PUSH8 => stack::push::<8, H> => stack_io(0, 1), immediate_size(8); + 0x68 => PUSH9 => stack::push::<9, H> => stack_io(0, 1), immediate_size(9); + 0x69 => PUSH10 => stack::push::<10, H> => stack_io(0, 1), immediate_size(10); + 0x6A => PUSH11 => stack::push::<11, H> => stack_io(0, 1), immediate_size(11); + 0x6B => PUSH12 => stack::push::<12, H> => stack_io(0, 1), immediate_size(12); + 0x6C => PUSH13 => stack::push::<13, H> => stack_io(0, 1), immediate_size(13); + 0x6D => PUSH14 => stack::push::<14, H> => stack_io(0, 1), immediate_size(14); + 0x6E => PUSH15 => stack::push::<15, H> => stack_io(0, 1), immediate_size(15); + 0x6F => PUSH16 => stack::push::<16, H> => stack_io(0, 1), immediate_size(16); + 0x70 => PUSH17 => stack::push::<17, H> => stack_io(0, 1), immediate_size(17); + 0x71 => PUSH18 => stack::push::<18, H> => stack_io(0, 1), immediate_size(18); + 0x72 => PUSH19 => stack::push::<19, H> => stack_io(0, 1), immediate_size(19); + 0x73 => PUSH20 => stack::push::<20, H> => stack_io(0, 1), immediate_size(20); + 0x74 => PUSH21 => stack::push::<21, H> => stack_io(0, 1), immediate_size(21); + 0x75 => PUSH22 => stack::push::<22, H> => stack_io(0, 1), immediate_size(22); + 0x76 => PUSH23 => stack::push::<23, H> => stack_io(0, 1), immediate_size(23); + 0x77 => PUSH24 => stack::push::<24, H> => stack_io(0, 1), immediate_size(24); + 0x78 => PUSH25 => stack::push::<25, H> => stack_io(0, 1), immediate_size(25); + 0x79 => PUSH26 => stack::push::<26, H> => stack_io(0, 1), immediate_size(26); + 0x7A => PUSH27 => stack::push::<27, H> => stack_io(0, 1), immediate_size(27); + 0x7B => PUSH28 => stack::push::<28, H> => stack_io(0, 1), immediate_size(28); + 0x7C => PUSH29 => stack::push::<29, H> => stack_io(0, 1), immediate_size(29); + 0x7D => PUSH30 => stack::push::<30, H> => stack_io(0, 1), immediate_size(30); + 0x7E => PUSH31 => stack::push::<31, H> => stack_io(0, 1), immediate_size(31); + 0x7F => PUSH32 => stack::push::<32, H> => stack_io(0, 1), immediate_size(32); + + 0x80 => DUP1 => stack::dup::<1, H> => stack_io(1, 2); + 0x81 => DUP2 => stack::dup::<2, H> => stack_io(2, 3); + 0x82 => DUP3 => stack::dup::<3, H> => stack_io(3, 4); + 0x83 => DUP4 => stack::dup::<4, H> => stack_io(4, 5); + 0x84 => DUP5 => stack::dup::<5, H> => stack_io(5, 6); + 0x85 => DUP6 => stack::dup::<6, H> => stack_io(6, 7); + 0x86 => DUP7 => stack::dup::<7, H> => stack_io(7, 8); + 0x87 => DUP8 => stack::dup::<8, H> => stack_io(8, 9); + 0x88 => DUP9 => stack::dup::<9, H> => stack_io(9, 10); + 0x89 => DUP10 => stack::dup::<10, H> => stack_io(10, 11); + 0x8A => DUP11 => stack::dup::<11, H> => stack_io(11, 12); + 0x8B => DUP12 => stack::dup::<12, H> => stack_io(12, 13); + 0x8C => DUP13 => stack::dup::<13, H> => stack_io(13, 14); + 0x8D => DUP14 => stack::dup::<14, H> => stack_io(14, 15); + 0x8E => DUP15 => stack::dup::<15, H> => stack_io(15, 16); + 0x8F => DUP16 => stack::dup::<16, H> => stack_io(16, 17); + + 0x90 => SWAP1 => stack::swap::<1, H> => stack_io(2, 2); + 0x91 => SWAP2 => stack::swap::<2, H> => stack_io(3, 3); + 0x92 => SWAP3 => stack::swap::<3, H> => stack_io(4, 4); + 0x93 => SWAP4 => stack::swap::<4, H> => stack_io(5, 5); + 0x94 => SWAP5 => stack::swap::<5, H> => stack_io(6, 6); + 0x95 => SWAP6 => stack::swap::<6, H> => stack_io(7, 7); + 0x96 => SWAP7 => stack::swap::<7, H> => stack_io(8, 8); + 0x97 => SWAP8 => stack::swap::<8, H> => stack_io(9, 9); + 0x98 => SWAP9 => stack::swap::<9, H> => stack_io(10, 10); + 0x99 => SWAP10 => stack::swap::<10, H> => stack_io(11, 11); + 0x9A => SWAP11 => stack::swap::<11, H> => stack_io(12, 12); + 0x9B => SWAP12 => stack::swap::<12, H> => stack_io(13, 13); + 0x9C => SWAP13 => stack::swap::<13, H> => stack_io(14, 14); + 0x9D => SWAP14 => stack::swap::<14, H> => stack_io(15, 15); + 0x9E => SWAP15 => stack::swap::<15, H> => stack_io(16, 16); + 0x9F => SWAP16 => stack::swap::<16, H> => stack_io(17, 17); + + 0xA0 => LOG0 => host::log::<0, H> => stack_io(2, 0); + 0xA1 => LOG1 => host::log::<1, H> => stack_io(3, 0); + 0xA2 => LOG2 => host::log::<2, H> => stack_io(4, 0); + 0xA3 => LOG3 => host::log::<3, H> => stack_io(5, 0); + 0xA4 => LOG4 => host::log::<4, H> => stack_io(6, 0); + // 0xA5 + // 0xA6 + // 0xA7 + // 0xA8 + // 0xA9 + // 0xAA + // 0xAB + // 0xAC + // 0xAD + // 0xAE + // 0xAF + // 0xB0 + // 0xB1 + // 0xB2 + // 0xB3 + // 0xB4 + // 0xB5 + // 0xB6 + // 0xB7 + // 0xB8 + // 0xB9 + // 0xBA + // 0xBB + // 0xBC + // 0xBD + // 0xBE + // 0xBF + // 0xC0 + // 0xC1 + // 0xC2 + // 0xC3 + // 0xC4 + // 0xC5 + // 0xC6 + // 0xC7 + // 0xC8 + // 0xC9 + // 0xCA + // 0xCB + // 0xCC + // 0xCD + // 0xCE + // 0xCF + 0xD0 => DATALOAD => data::data_load => stack_io(1, 1); + 0xD1 => DATALOADN => data::data_loadn => stack_io(0, 1), immediate_size(2); + 0xD2 => DATASIZE => data::data_size => stack_io(0, 1); + 0xD3 => DATACOPY => data::data_copy => stack_io(3, 0); + // 0xD4 + // 0xD5 + // 0xD6 + // 0xD7 + // 0xD8 + // 0xD9 + // 0xDA + // 0xDB + // 0xDC + // 0xDD + // 0xDE + // 0xDF + 0xE0 => RJUMP => control::rjump => stack_io(0, 0), immediate_size(2), terminating; + 0xE1 => RJUMPI => control::rjumpi => stack_io(1, 0), immediate_size(2); + 0xE2 => RJUMPV => control::rjumpv => stack_io(1, 0), immediate_size(1); + 0xE3 => CALLF => control::callf => stack_io(0, 0), immediate_size(2); + 0xE4 => RETF => control::retf => stack_io(0, 0), terminating; + 0xE5 => JUMPF => control::jumpf => stack_io(0, 0), immediate_size(2), terminating; + 0xE6 => DUPN => stack::dupn => stack_io(0, 1), immediate_size(1); + 0xE7 => SWAPN => stack::swapn => stack_io(0, 0), immediate_size(1); + 0xE8 => EXCHANGE => stack::exchange => stack_io(0, 0), immediate_size(1); + // 0xE9 + // 0xEA + // 0xEB + 0xEC => EOFCREATE => contract::eofcreate => stack_io(4, 1), immediate_size(1); + 0xED => TXCREATE => contract::txcreate => stack_io(5, 1); + 0xEE => RETURNCONTRACT => contract::return_contract => stack_io(2, 0), immediate_size(1), terminating; + // 0xEF + 0xF0 => CREATE => contract::create:: => stack_io(3, 1), not_eof; + 0xF1 => CALL => contract::call:: => stack_io(7, 1), not_eof; + 0xF2 => CALLCODE => contract::call_code:: => stack_io(7, 1), not_eof; + 0xF3 => RETURN => control::ret => stack_io(2, 0), terminating; + 0xF4 => DELEGATECALL => contract::delegate_call:: => stack_io(6, 1), not_eof; + 0xF5 => CREATE2 => contract::create:: => stack_io(4, 1), not_eof; + // 0xF6 + 0xF7 => RETURNDATALOAD => system::returndataload => stack_io(1, 1); + 0xF8 => EXTCALL => contract::extcall:: => stack_io(4, 1); + 0xF9 => EXFCALL => contract::extdcall:: => stack_io(3, 1); + 0xFA => STATICCALL => contract::static_call:: => stack_io(6, 1), not_eof; + 0xFB => EXTSCALL => contract::extscall => stack_io(3, 1); + // 0xFC + 0xFD => REVERT => control::revert:: => stack_io(2, 0), terminating; + 0xFE => INVALID => control::invalid => stack_io(0, 0), terminating; + 0xFF => SELFDESTRUCT => host::selfdestruct:: => stack_io(1, 0), not_eof, terminating; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_opcode() { + let opcode = OpCode::new(0x00).unwrap(); + assert!(!opcode.is_jumpdest()); + assert!(!opcode.is_jump()); + assert!(!opcode.is_push()); + assert_eq!(opcode.as_str(), "STOP"); + assert_eq!(opcode.get(), 0x00); + } + + #[test] + fn test_eof_disable() { + const REJECTED_IN_EOF: &[u8] = &[ + 0x38, 0x39, 0x3b, 0x3c, 0x3f, 0x5a, 0xf1, 0xf2, 0xf4, 0xfa, 0xff, + ]; + + for opcode in REJECTED_IN_EOF { + let opcode = OpCode::new(*opcode).unwrap(); + assert!( + opcode.info().is_disabled_in_eof(), + "not disabled in EOF: {opcode:#?}", + ); + } + } + + #[test] + fn test_immediate_size() { + let mut expected = [0u8; 256]; + // PUSH opcodes + for push in PUSH1..=PUSH32 { + expected[push as usize] = push - PUSH1 + 1; + } + expected[DATALOADN as usize] = 2; + expected[RJUMP as usize] = 2; + expected[RJUMPI as usize] = 2; + expected[RJUMPV as usize] = 1; + expected[CALLF as usize] = 2; + expected[JUMPF as usize] = 2; + expected[DUPN as usize] = 1; + expected[SWAPN as usize] = 1; + expected[EXCHANGE as usize] = 1; + expected[EOFCREATE as usize] = 1; + expected[RETURNCONTRACT as usize] = 1; + + for (i, opcode) in OPCODE_INFO_JUMPTABLE.iter().enumerate() { + if let Some(opcode) = opcode { + assert_eq!( + opcode.immediate_size(), + expected[i], + "immediate_size check failed for {opcode:#?}", + ); + } + } + } + + #[test] + fn test_enabled_opcodes() { + // List obtained from https://eips.ethereum.org/EIPS/eip-3670 + let opcodes = [ + 0x10..=0x1d, + 0x20..=0x20, + 0x30..=0x3f, + 0x40..=0x48, + 0x50..=0x5b, + 0x54..=0x5f, + 0x60..=0x6f, + 0x70..=0x7f, + 0x80..=0x8f, + 0x90..=0x9f, + 0xa0..=0xa4, + 0xf0..=0xf5, + 0xfa..=0xfa, + 0xfd..=0xfd, + //0xfe, + 0xff..=0xff, + ]; + for i in opcodes { + for opcode in i { + OpCode::new(opcode).expect("Opcode should be valid and enabled"); + } + } + } + + #[test] + fn test_terminating_opcodes() { + let terminating = [ + RETF, + REVERT, + RETURN, + INVALID, + SELFDESTRUCT, + RETURNCONTRACT, + STOP, + RJUMP, + JUMPF, + ]; + let mut opcodes = [false; 256]; + for terminating in terminating.iter() { + opcodes[*terminating as usize] = true; + } + + for (i, opcode) in OPCODE_INFO_JUMPTABLE.into_iter().enumerate() { + assert_eq!( + opcode.map(|opcode| opcode.terminating).unwrap_or_default(), + opcodes[i], + "Opcode {:?} terminating chack failed.", + opcode + ); + } + } + + #[test] + #[cfg(feature = "parse")] + fn test_parsing() { + for i in 0..=u8::MAX { + if let Some(op) = OpCode::new(i) { + assert_eq!(OpCode::parse(op.as_str()), Some(op)); + } + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/src/opcode/eof_printer.md b/docs/revm-python-spec/revm-verif/revm/interpreter/src/opcode/eof_printer.md new file mode 100644 index 00000000..6ae6b711 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/src/opcode/eof_printer.md @@ -0,0 +1,73 @@ +# ๐Ÿฆ€ eof_printer.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/src/opcode/eof_printer.rs) + +```rust +#[cfg(feature = "std")] +pub fn print_eof_code(code: &[u8]) { + use super::*; + use crate::instructions::utility::read_i16; + use revm_primitives::hex; + + // We can check validity and jump destinations in one pass. + let mut i = 0; + while i < code.len() { + let op = code[i]; + let opcode = &OPCODE_INFO_JUMPTABLE[op as usize]; + + let Some(opcode) = opcode else { + println!("Unknown opcode: 0x{:02X}", op); + i += 1; + continue; + }; + + if opcode.immediate_size() != 0 { + // check if the opcode immediate are within the bounds of the code + if i + opcode.immediate_size() as usize >= code.len() { + println!("Malformed code: immediate out of bounds"); + break; + } + } + + print!("{}", opcode.name()); + if opcode.immediate_size() != 0 { + print!( + " : 0x{:}", + hex::encode(&code[i + 1..i + 1 + opcode.immediate_size() as usize]) + ); + } + + let mut rjumpv_additional_immediates = 0; + if op == RJUMPV { + let max_index = code[i + 1] as usize; + let len = max_index + 1; + // and max_index+1 is to get size of vtable as index starts from 0. + rjumpv_additional_immediates = len * 2; + + // +1 is for max_index byte + if i + 1 + rjumpv_additional_immediates >= code.len() { + println!("Malformed code: immediate out of bounds"); + break; + } + + for vtablei in 0..len { + let offset = unsafe { read_i16(code.as_ptr().add(i + 2 + 2 * vtablei)) } as isize; + println!("RJUMPV[{vtablei}]: 0x{offset:04X}({offset})"); + } + } + + i += 1 + opcode.immediate_size() as usize + rjumpv_additional_immediates; + } +} + +#[cfg(test)] +mod test { + use super::*; + use revm_primitives::hex; + + #[test] + fn sanity_test() { + print_eof_code(&hex!("6001e200ffff00")); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/interpreter/tests/eof.md b/docs/revm-python-spec/revm-verif/revm/interpreter/tests/eof.md new file mode 100644 index 00000000..f20e1e02 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/interpreter/tests/eof.md @@ -0,0 +1,190 @@ +# ๐Ÿฆ€ eof.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/interpreter/tests/eof.rs) + +```rust +use revm_interpreter::analysis::{validate_raw_eof, EofError}; +use revm_primitives::{Bytes, Eof}; +use serde::Deserialize; +use std::{ + collections::BTreeMap, + path::{Path, PathBuf}, + time::Instant, +}; +use walkdir::{DirEntry, WalkDir}; + +/* +Types of error: { + FalsePossitive: 1, + Error( + Validation( + OpcodeDisabled, + ), + ): 19, +} +*/ +#[test] +fn eof_run_all_tests() { + let eof_tests = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/EOFTests"); + run_test(&eof_tests) +} + +/* +Types of error: { + FalsePossitive: 1, +} +Passed tests: 1262/1263 +EOF_EofCreateWithTruncatedContainer TODO +*/ +#[test] +fn eof_validation() { + let eof_tests = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/EOFTests/eof_validation"); + run_test(&eof_tests) +} + +/* +Types of error: { + OpcodeDisabled: 8, +} +Passed tests: 194/202 +Probably same as below. +*/ +#[test] +fn eof_validation_eip5450() { + let eof_tests = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/EOFTests/EIP5450"); + run_test(&eof_tests) +} + +/* +Types of error: { + OpcodeDisabled: 9, +} +Passed tests: 290/299 + */ +// 0x60018080808080fa00 STATICCALL validInvalid - validInvalid_89 +// 0x60018080808080f400 DELEGATECALL validInvalid - validInvalid_88 +// 0x60018080808080f400 CALL validInvalid - validInvalid_86 +// 0x38e4 CODESIZE validInvalid - validInvalid_4 +// 0x60013f00 EXTCODEHASH validInvalid - validInvalid_39 +// 0x60018080803c00 EXTCODECOPY validInvalid - validInvalid_37 +// 0x60013b00 EXTCODESIZE validInvalid - validInvalid_36 +// 0x600180803900 CODECOPY validInvalid - validInvalid_35 +// 0x5a00 GAS validInvalid - validInvalid_60 +// 0xfe opcode is considered valid, should it be disabled? +#[test] +fn eof_validation_eip3670() { + let eof_tests = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/EOFTests/EIP3670"); + run_test(&eof_tests) +} + +/// PASSING ALL +#[test] +fn eof_validation_eip4750() { + let inst = Instant::now(); + let eof_tests = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/EOFTests/EIP4750"); + run_test(&eof_tests); + println!("Elapsed:{:?}", inst.elapsed()) +} + +/// PASSING ALL +#[test] +fn eof_validation_eip3540() { + let eof_tests = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/EOFTests/EIP3540"); + run_test(&eof_tests) +} + +/// PASSING ALL +#[test] +fn eof_validation_eip4200() { + let eof_tests = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/EOFTests/EIP4200"); + run_test(&eof_tests); +} + +pub fn run_test(path: &Path) { + let test_files = find_all_json_tests(path); + let mut test_sum = 0; + let mut passed_tests = 0; + + #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] + enum ErrorType { + FalsePositive, + Error(EofError), + } + let mut types_of_error: BTreeMap = BTreeMap::new(); + for test_file in test_files { + let s = std::fs::read_to_string(test_file).unwrap(); + let suite: TestSuite = serde_json::from_str(&s).unwrap(); + for (name, test_unit) in suite.0 { + for (vector_name, test_vector) in test_unit.vectors { + test_sum += 1; + let res = validate_raw_eof(test_vector.code.clone()); + if res.is_ok() != test_vector.results.prague.result { + let eof = Eof::decode(test_vector.code.clone()); + println!( + "\nTest failed: {} - {}\nresult:{:?}\nrevm err_result:{:#?}\nbytes:{:?}\n,eof:{eof:#?}", + name, + vector_name, + test_vector.results.prague, + res.as_ref().err(), + test_vector.code + ); + *types_of_error + .entry( + res.err() + .map(ErrorType::Error) + .unwrap_or(ErrorType::FalsePositive), + ) + .or_default() += 1; + } else { + //println!("Test passed: {} - {}", name, vector_name); + passed_tests += 1; + } + } + } + } + println!("Types of error: {:#?}", types_of_error); + println!("Passed tests: {}/{}", passed_tests, test_sum); +} + +pub fn find_all_json_tests(path: &Path) -> Vec { + WalkDir::new(path) + .into_iter() + .filter_map(|e| e.ok()) + .filter(|e| e.file_name().to_string_lossy().ends_with(".json")) + .map(DirEntry::into_path) + .collect::>() +} + +#[derive(Debug, PartialEq, Eq, Deserialize)] +pub struct TestSuite(pub BTreeMap); + +#[derive(Debug, PartialEq, Eq, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct TestUnit { + /// Test info is optional + #[serde(default, rename = "_info")] + pub info: Option, + + pub vectors: BTreeMap, +} + +#[derive(Debug, PartialEq, Eq, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct TestVector { + code: Bytes, + results: PragueResult, +} + +#[derive(Debug, PartialEq, Eq, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct PragueResult { + #[serde(rename = "Prague")] + prague: Result, +} + +#[derive(Debug, PartialEq, Eq, Deserialize)] +pub struct Result { + result: bool, + exception: Option, +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/benches/bench.md b/docs/revm-python-spec/revm-verif/revm/precompile/benches/bench.md new file mode 100644 index 00000000..634816e1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/benches/bench.md @@ -0,0 +1,133 @@ +# ๐Ÿฆ€ bench.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/benches/bench.rs) + +```rust +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use revm_precompile::{ + bn128::{ + pair::{ISTANBUL_PAIR_BASE, ISTANBUL_PAIR_PER_POINT}, + run_pair, + }, + kzg_point_evaluation::run, + secp256k1::ec_recover_run, + Bytes, +}; +use revm_primitives::{hex, keccak256, Env, U256, VERSIONED_HASH_VERSION_KZG}; +use secp256k1::{Message, SecretKey, SECP256K1}; +use sha2::{Digest, Sha256}; + +/// Benchmarks different cryptography-related precompiles. +pub fn benchmark_crypto_precompiles(c: &mut Criterion) { + let mut group = c.benchmark_group("Crypto Precompile benchmarks"); + let group_name = |description: &str| format!("precompile bench | {description}"); + + // === ECPAIRING === + + // set up ecpairing input + let input = hex::decode( + "\ + 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ + 3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\ + 209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\ + 04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\ + 2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\ + 120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\ + 111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\ + 2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\ + 198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\ + 1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\ + 090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\ + 12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + ) + .unwrap(); + + let res = run_pair( + &input, + ISTANBUL_PAIR_PER_POINT, + ISTANBUL_PAIR_BASE, + u64::MAX, + ) + .unwrap() + .0; + + println!("gas used by regular pairing call: {:?}", res); + + // === ECRECOVER === + + // generate secp256k1 signature + let data = hex::decode("1337133713371337").unwrap(); + let hash = keccak256(data); + let secret_key = SecretKey::new(&mut rand::thread_rng()); + + let message = Message::from_digest_slice(&hash[..]).unwrap(); + let s = SECP256K1.sign_ecdsa_recoverable(&message, &secret_key); + let (rec_id, data) = s.serialize_compact(); + let mut rec_id = rec_id.to_i32() as u8; + assert_eq!(rec_id, 0); + rec_id += 27; + + let mut message_and_signature = [0u8; 128]; + message_and_signature[0..32].copy_from_slice(&hash[..]); + + // fit signature into format the precompile expects + let rec_id = U256::from(rec_id as u64); + message_and_signature[32..64].copy_from_slice(&rec_id.to_be_bytes::<32>()); + message_and_signature[64..128].copy_from_slice(&data); + + let message_and_signature = Bytes::from(message_and_signature); + let gas = ec_recover_run(&message_and_signature, u64::MAX).unwrap(); + println!("gas used by ecrecover precompile: {:?}", gas); + + // === POINT_EVALUATION === + + // now check kzg precompile gas + let commitment = hex!("8f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7").to_vec(); + let mut versioned_hash = Sha256::digest(&commitment).to_vec(); + versioned_hash[0] = VERSIONED_HASH_VERSION_KZG; + let z = hex!("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000").to_vec(); + let y = hex!("1522a4a7f34e1ea350ae07c29c96c7e79655aa926122e95fe69fcbd932ca49e9").to_vec(); + let proof = hex!("a62ad71d14c5719385c0686f1871430475bf3a00f0aa3f7b8dd99a9abc2160744faf0070725e00b60ad9a026a15b1a8c").to_vec(); + + let kzg_input = [versioned_hash, z, y, commitment, proof].concat().into(); + + let gas = 50000; + let env = Env::default(); + let (actual_gas, _actual_output) = run(&kzg_input, gas, &env).unwrap(); + println!("gas used by kzg precompile: {:?}", actual_gas); + + group.bench_function(group_name("ecrecover precompile"), |b| { + b.iter(|| { + ec_recover_run(&message_and_signature, u64::MAX).unwrap(); + black_box(()) + }) + }); + + group.bench_function(group_name("ecpairing precompile"), |b| { + b.iter(|| { + run_pair( + &input, + ISTANBUL_PAIR_PER_POINT, + ISTANBUL_PAIR_BASE, + u64::MAX, + ) + .unwrap(); + black_box(()) + }) + }); + + group.bench_function(group_name("kzg precompile"), |b| { + b.iter(|| { + run(&kzg_input, gas, &env).unwrap(); + black_box(()) + }) + }); +} + +criterion_group! { + name = benches; + config = Criterion::default(); + targets = benchmark_crypto_precompiles +} +criterion_main!(benches); +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/src/blake2.md b/docs/revm-python-spec/revm-verif/revm/precompile/src/blake2.md new file mode 100644 index 00000000..65790cd3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/src/blake2.md @@ -0,0 +1,140 @@ +# ๐Ÿฆ€ blake2.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/src/blake2.rs) + +```rust +use crate::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; +use revm_primitives::Bytes; + +const F_ROUND: u64 = 1; +const INPUT_LENGTH: usize = 213; + +pub const FUN: PrecompileWithAddress = + PrecompileWithAddress(crate::u64_to_address(9), Precompile::Standard(run)); + +/// reference: +/// input format: +/// [4 bytes for rounds][64 bytes for h][128 bytes for m][8 bytes for t_0][8 bytes for t_1][1 byte for f] +pub fn run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + let input = &input[..]; + + if input.len() != INPUT_LENGTH { + return Err(Error::Blake2WrongLength); + } + + let f = match input[212] { + 1 => true, + 0 => false, + _ => return Err(Error::Blake2WrongFinalIndicatorFlag), + }; + + // rounds 4 bytes + let rounds = u32::from_be_bytes(input[..4].try_into().unwrap()) as usize; + let gas_used = rounds as u64 * F_ROUND; + if gas_used > gas_limit { + return Err(Error::OutOfGas); + } + + let mut h = [0u64; 8]; + let mut m = [0u64; 16]; + + for (i, pos) in (4..68).step_by(8).enumerate() { + h[i] = u64::from_le_bytes(input[pos..pos + 8].try_into().unwrap()); + } + for (i, pos) in (68..196).step_by(8).enumerate() { + m[i] = u64::from_le_bytes(input[pos..pos + 8].try_into().unwrap()); + } + let t = [ + u64::from_le_bytes(input[196..196 + 8].try_into().unwrap()), + u64::from_le_bytes(input[204..204 + 8].try_into().unwrap()), + ]; + + algo::compress(rounds, &mut h, m, t, f); + + let mut out = [0u8; 64]; + for (i, h) in (0..64).step_by(8).zip(h.iter()) { + out[i..i + 8].copy_from_slice(&h.to_le_bytes()); + } + + Ok((gas_used, out.into())) +} + +pub mod algo { + /// SIGMA from spec: + pub const SIGMA: [[usize; 16]; 10] = [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], + [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], + [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], + [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], + [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], + [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], + [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], + [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], + [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], + ]; + + /// got IV from: + pub const IV: [u64; 8] = [ + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179, + ]; + + #[inline] + #[allow(clippy::many_single_char_names)] + /// G function: + pub fn g(v: &mut [u64], a: usize, b: usize, c: usize, d: usize, x: u64, y: u64) { + v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); + v[d] = (v[d] ^ v[a]).rotate_right(32); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(24); + v[a] = v[a].wrapping_add(v[b]).wrapping_add(y); + v[d] = (v[d] ^ v[a]).rotate_right(16); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(63); + } + + // Compression function F takes as an argument the state vector "h", + // message block vector "m" (last block is padded with zeros to full + // block size, if required), 2w-bit offset counter "t", and final block + // indicator flag "f". Local vector v[0..15] is used in processing. F + // returns a new state vector. The number of rounds, "r", is 12 for + // BLAKE2b and 10 for BLAKE2s. Rounds are numbered from 0 to r - 1. + #[allow(clippy::many_single_char_names)] + pub fn compress(rounds: usize, h: &mut [u64; 8], m: [u64; 16], t: [u64; 2], f: bool) { + let mut v = [0u64; 16]; + v[..h.len()].copy_from_slice(h); // First half from state. + v[h.len()..].copy_from_slice(&IV); // Second half from IV. + + v[12] ^= t[0]; + v[13] ^= t[1]; + + if f { + v[14] = !v[14] // Invert all bits if the last-block-flag is set. + } + for i in 0..rounds { + // Message word selection permutation for this round. + let s = &SIGMA[i % 10]; + g(&mut v, 0, 4, 8, 12, m[s[0]], m[s[1]]); + g(&mut v, 1, 5, 9, 13, m[s[2]], m[s[3]]); + g(&mut v, 2, 6, 10, 14, m[s[4]], m[s[5]]); + g(&mut v, 3, 7, 11, 15, m[s[6]], m[s[7]]); + + g(&mut v, 0, 5, 10, 15, m[s[8]], m[s[9]]); + g(&mut v, 1, 6, 11, 12, m[s[10]], m[s[11]]); + g(&mut v, 2, 7, 8, 13, m[s[12]], m[s[13]]); + g(&mut v, 3, 4, 9, 14, m[s[14]], m[s[15]]); + } + + for i in 0..8 { + h[i] ^= v[i] ^ v[i + 8]; + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/src/bn128.md b/docs/revm-python-spec/revm-verif/revm/precompile/src/bn128.md new file mode 100644 index 00000000..d7b368fb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/src/bn128.md @@ -0,0 +1,495 @@ +# ๐Ÿฆ€ bn128.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/src/bn128.rs) + +```rust +use crate::{ + utilities::{bool_to_bytes32, right_pad}, + Address, Error, Precompile, PrecompileResult, PrecompileWithAddress, +}; +use bn::{AffineG1, AffineG2, Fq, Fq2, Group, Gt, G1, G2}; + +pub mod add { + use super::*; + + const ADDRESS: Address = crate::u64_to_address(6); + + pub const ISTANBUL_ADD_GAS_COST: u64 = 150; + pub const ISTANBUL: PrecompileWithAddress = PrecompileWithAddress( + ADDRESS, + Precompile::Standard(|input, gas_limit| run_add(input, ISTANBUL_ADD_GAS_COST, gas_limit)), + ); + + pub const BYZANTIUM_ADD_GAS_COST: u64 = 500; + pub const BYZANTIUM: PrecompileWithAddress = PrecompileWithAddress( + ADDRESS, + Precompile::Standard(|input, gas_limit| run_add(input, BYZANTIUM_ADD_GAS_COST, gas_limit)), + ); +} + +pub mod mul { + use super::*; + + const ADDRESS: Address = crate::u64_to_address(7); + + pub const ISTANBUL_MUL_GAS_COST: u64 = 6_000; + pub const ISTANBUL: PrecompileWithAddress = PrecompileWithAddress( + ADDRESS, + Precompile::Standard(|input, gas_limit| run_mul(input, ISTANBUL_MUL_GAS_COST, gas_limit)), + ); + + pub const BYZANTIUM_MUL_GAS_COST: u64 = 40_000; + pub const BYZANTIUM: PrecompileWithAddress = PrecompileWithAddress( + ADDRESS, + Precompile::Standard(|input, gas_limit| run_mul(input, BYZANTIUM_MUL_GAS_COST, gas_limit)), + ); +} + +pub mod pair { + use super::*; + + const ADDRESS: Address = crate::u64_to_address(8); + + pub const ISTANBUL_PAIR_PER_POINT: u64 = 34_000; + pub const ISTANBUL_PAIR_BASE: u64 = 45_000; + pub const ISTANBUL: PrecompileWithAddress = PrecompileWithAddress( + ADDRESS, + Precompile::Standard(|input, gas_limit| { + run_pair( + input, + ISTANBUL_PAIR_PER_POINT, + ISTANBUL_PAIR_BASE, + gas_limit, + ) + }), + ); + + pub const BYZANTIUM_PAIR_PER_POINT: u64 = 80_000; + pub const BYZANTIUM_PAIR_BASE: u64 = 100_000; + pub const BYZANTIUM: PrecompileWithAddress = PrecompileWithAddress( + ADDRESS, + Precompile::Standard(|input, gas_limit| { + run_pair( + input, + BYZANTIUM_PAIR_PER_POINT, + BYZANTIUM_PAIR_BASE, + gas_limit, + ) + }), + ); +} + +/// Input length for the add operation. +/// `ADD` takes two uncompressed G1 points (64 bytes each). +pub const ADD_INPUT_LEN: usize = 64 + 64; + +/// Input length for the multiplication operation. +/// `MUL` takes an uncompressed G1 point (64 bytes) and scalar (32 bytes). +pub const MUL_INPUT_LEN: usize = 64 + 32; + +/// Pair element length. +/// `PAIR` elements are composed of an uncompressed G1 point (64 bytes) and an uncompressed G2 point +/// (128 bytes). +pub const PAIR_ELEMENT_LEN: usize = 64 + 128; + +/// Reads a single `Fq` from the input slice. +/// +/// # Panics +/// +/// Panics if the input is not at least 32 bytes long. +#[inline] +pub fn read_fq(input: &[u8]) -> Result { + Fq::from_slice(&input[..32]).map_err(|_| Error::Bn128FieldPointNotAMember) +} + +/// Reads the `x` and `y` points from the input slice. +/// +/// # Panics +/// +/// Panics if the input is not at least 64 bytes long. +#[inline] +pub fn read_point(input: &[u8]) -> Result { + let px = read_fq(&input[0..32])?; + let py = read_fq(&input[32..64])?; + new_g1_point(px, py) +} + +/// Creates a new `G1` point from the given `x` and `y` coordinates. +pub fn new_g1_point(px: Fq, py: Fq) -> Result { + if px == Fq::zero() && py == Fq::zero() { + Ok(G1::zero()) + } else { + AffineG1::new(px, py) + .map(Into::into) + .map_err(|_| Error::Bn128AffineGFailedToCreate) + } +} + +pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { + if gas_cost > gas_limit { + return Err(Error::OutOfGas); + } + + let input = right_pad::(input); + + let p1 = read_point(&input[..64])?; + let p2 = read_point(&input[64..])?; + + let mut output = [0u8; 64]; + if let Some(sum) = AffineG1::from_jacobian(p1 + p2) { + sum.x().to_big_endian(&mut output[..32]).unwrap(); + sum.y().to_big_endian(&mut output[32..]).unwrap(); + } + Ok((gas_cost, output.into())) +} + +pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { + if gas_cost > gas_limit { + return Err(Error::OutOfGas); + } + + let input = right_pad::(input); + + let p = read_point(&input[..64])?; + + // `Fr::from_slice` can only fail when the length is not 32. + let fr = bn::Fr::from_slice(&input[64..96]).unwrap(); + + let mut output = [0u8; 64]; + if let Some(mul) = AffineG1::from_jacobian(p * fr) { + mul.x().to_big_endian(&mut output[..32]).unwrap(); + mul.y().to_big_endian(&mut output[32..]).unwrap(); + } + Ok((gas_cost, output.into())) +} + +pub fn run_pair( + input: &[u8], + pair_per_point_cost: u64, + pair_base_cost: u64, + gas_limit: u64, +) -> PrecompileResult { + let gas_used = (input.len() / PAIR_ELEMENT_LEN) as u64 * pair_per_point_cost + pair_base_cost; + if gas_used > gas_limit { + return Err(Error::OutOfGas); + } + + if input.len() % PAIR_ELEMENT_LEN != 0 { + return Err(Error::Bn128PairLength); + } + + let success = if input.is_empty() { + true + } else { + let elements = input.len() / PAIR_ELEMENT_LEN; + + let mut mul = Gt::one(); + for idx in 0..elements { + let read_fq_at = |n: usize| { + debug_assert!(n < PAIR_ELEMENT_LEN / 32); + let start = idx * PAIR_ELEMENT_LEN + n * 32; + // SAFETY: We're reading `6 * 32 == PAIR_ELEMENT_LEN` bytes from `input[idx..]` + // per iteration. This is guaranteed to be in-bounds. + let slice = unsafe { input.get_unchecked(start..start + 32) }; + Fq::from_slice(slice).map_err(|_| Error::Bn128FieldPointNotAMember) + }; + let ax = read_fq_at(0)?; + let ay = read_fq_at(1)?; + let bay = read_fq_at(2)?; + let bax = read_fq_at(3)?; + let bby = read_fq_at(4)?; + let bbx = read_fq_at(5)?; + + let a = new_g1_point(ax, ay)?; + let b = { + let ba = Fq2::new(bax, bay); + let bb = Fq2::new(bbx, bby); + if ba.is_zero() && bb.is_zero() { + G2::zero() + } else { + G2::from(AffineG2::new(ba, bb).map_err(|_| Error::Bn128AffineGFailedToCreate)?) + } + }; + + mul = mul * bn::pairing(a, b); + } + + mul == Gt::one() + }; + Ok((gas_used, bool_to_bytes32(success))) +} + +#[cfg(test)] +mod tests { + use crate::bn128::add::BYZANTIUM_ADD_GAS_COST; + use crate::bn128::mul::BYZANTIUM_MUL_GAS_COST; + use crate::bn128::pair::{BYZANTIUM_PAIR_BASE, BYZANTIUM_PAIR_PER_POINT}; + use revm_primitives::hex; + + use super::*; + + #[test] + fn test_alt_bn128_add() { + let input = hex::decode( + "\ + 18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9\ + 063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266\ + 07c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed\ + 06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7", + ) + .unwrap(); + let expected = hex::decode( + "\ + 2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703\ + 301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915", + ) + .unwrap(); + + let (_, res) = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); + assert_eq!(res, expected); + + // zero sum test + let input = hex::decode( + "\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(); + let expected = hex::decode( + "\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(); + + let (_, res) = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); + assert_eq!(res, expected); + + // out of gas test + let input = hex::decode( + "\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(); + + let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 499); + println!("{:?}", res); + assert!(matches!(res, Err(Error::OutOfGas))); + + // no input test + let input = [0u8; 0]; + let expected = hex::decode( + "\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(); + + let (_, res) = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); + assert_eq!(res, expected); + + // point not on curve fail + let input = hex::decode( + "\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap(); + + let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500); + assert!(matches!(res, Err(Error::Bn128AffineGFailedToCreate))); + } + + #[test] + fn test_alt_bn128_mul() { + let input = hex::decode( + "\ + 2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb7\ + 21611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204\ + 00000000000000000000000000000000000000000000000011138ce750fa15c2", + ) + .unwrap(); + let expected = hex::decode( + "\ + 070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c\ + 031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc", + ) + .unwrap(); + + let (_, res) = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); + assert_eq!(res, expected); + + // out of gas test + let input = hex::decode( + "\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0200000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(); + + let res = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 39_999); + assert!(matches!(res, Err(Error::OutOfGas))); + + // zero multiplication test + let input = hex::decode( + "\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0200000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(); + let expected = hex::decode( + "\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(); + + let (_, res) = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); + assert_eq!(res, expected); + + // no input test + let input = [0u8; 0]; + let expected = hex::decode( + "\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(); + + let (_, res) = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); + assert_eq!(res, expected); + + // point not on curve fail + let input = hex::decode( + "\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 0f00000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(); + + let res = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000); + assert!(matches!(res, Err(Error::Bn128AffineGFailedToCreate))); + } + + #[test] + fn test_alt_bn128_pair() { + let input = hex::decode( + "\ + 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ + 3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\ + 209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\ + 04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\ + 2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\ + 120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\ + 111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\ + 2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\ + 198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\ + 1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\ + 090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\ + 12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + ) + .unwrap(); + let expected = + hex::decode("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(); + + let (_, res) = run_pair( + &input, + BYZANTIUM_PAIR_PER_POINT, + BYZANTIUM_PAIR_BASE, + 260_000, + ) + .unwrap(); + assert_eq!(res, expected); + + // out of gas test + let input = hex::decode( + "\ + 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ + 3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\ + 209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\ + 04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\ + 2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\ + 120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\ + 111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\ + 2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\ + 198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\ + 1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\ + 090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\ + 12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + ) + .unwrap(); + + let res = run_pair( + &input, + BYZANTIUM_PAIR_PER_POINT, + BYZANTIUM_PAIR_BASE, + 259_999, + ); + assert!(matches!(res, Err(Error::OutOfGas))); + + // no input test + let input = [0u8; 0]; + let expected = + hex::decode("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(); + + let (_, res) = run_pair( + &input, + BYZANTIUM_PAIR_PER_POINT, + BYZANTIUM_PAIR_BASE, + 260_000, + ) + .unwrap(); + assert_eq!(res, expected); + + // point not on curve fail + let input = hex::decode( + "\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap(); + + let res = run_pair( + &input, + BYZANTIUM_PAIR_PER_POINT, + BYZANTIUM_PAIR_BASE, + 260_000, + ); + assert!(matches!(res, Err(Error::Bn128AffineGFailedToCreate))); + + // invalid input length + let input = hex::decode( + "\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 111111111111111111111111111111\ + ", + ) + .unwrap(); + + let res = run_pair( + &input, + BYZANTIUM_PAIR_PER_POINT, + BYZANTIUM_PAIR_BASE, + 260_000, + ); + assert!(matches!(res, Err(Error::Bn128PairLength))); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/src/hash.md b/docs/revm-python-spec/revm-verif/revm/precompile/src/hash.md new file mode 100644 index 00000000..f4e64b92 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/src/hash.md @@ -0,0 +1,48 @@ +# ๐Ÿฆ€ hash.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/src/hash.rs) + +```rust +use super::calc_linear_cost_u32; +use crate::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; +use revm_primitives::Bytes; +use sha2::Digest; + +pub const SHA256: PrecompileWithAddress = + PrecompileWithAddress(crate::u64_to_address(2), Precompile::Standard(sha256_run)); + +pub const RIPEMD160: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(3), + Precompile::Standard(ripemd160_run), +); + +/// See: +/// See: +/// See: +pub fn sha256_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + let cost = calc_linear_cost_u32(input.len(), 60, 12); + if cost > gas_limit { + Err(Error::OutOfGas) + } else { + let output = sha2::Sha256::digest(input); + Ok((cost, output.to_vec().into())) + } +} + +/// See: +/// See: +/// See: +pub fn ripemd160_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + let gas_used = calc_linear_cost_u32(input.len(), 600, 120); + if gas_used > gas_limit { + Err(Error::OutOfGas) + } else { + let mut hasher = ripemd::Ripemd160::new(); + hasher.update(input); + + let mut output = [0u8; 32]; + hasher.finalize_into((&mut output[12..]).into()); + Ok((gas_used, output.to_vec().into())) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/src/identity.md b/docs/revm-python-spec/revm-verif/revm/precompile/src/identity.md new file mode 100644 index 00000000..6ecc7859 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/src/identity.md @@ -0,0 +1,29 @@ +# ๐Ÿฆ€ identity.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/src/identity.rs) + +```rust +use super::calc_linear_cost_u32; +use crate::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; +use revm_primitives::Bytes; + +pub const FUN: PrecompileWithAddress = + PrecompileWithAddress(crate::u64_to_address(4), Precompile::Standard(identity_run)); + +/// The base cost of the operation. +pub const IDENTITY_BASE: u64 = 15; +/// The cost per word. +pub const IDENTITY_PER_WORD: u64 = 3; + +/// Takes the input bytes, copies them, and returns it as the output. +/// +/// See: +/// See: +pub fn identity_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + let gas_used = calc_linear_cost_u32(input.len(), IDENTITY_BASE, IDENTITY_PER_WORD); + if gas_used > gas_limit { + return Err(Error::OutOfGas); + } + Ok((gas_used, input.clone())) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/src/kzg_point_evaluation.md b/docs/revm-python-spec/revm-verif/revm/precompile/src/kzg_point_evaluation.md new file mode 100644 index 00000000..1c840dc4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/src/kzg_point_evaluation.md @@ -0,0 +1,126 @@ +# ๐Ÿฆ€ kzg_point_evaluation.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/src/kzg_point_evaluation.rs) + +```rust +use crate::{Address, Error, Precompile, PrecompileResult, PrecompileWithAddress}; +use c_kzg::{Bytes32, Bytes48, KzgProof, KzgSettings}; +use revm_primitives::{hex_literal::hex, Bytes, Env}; +use sha2::{Digest, Sha256}; + +pub const POINT_EVALUATION: PrecompileWithAddress = + PrecompileWithAddress(ADDRESS, Precompile::Env(run)); + +pub const ADDRESS: Address = crate::u64_to_address(0x0A); +pub const GAS_COST: u64 = 50_000; +pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01; + +/// `U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes() ++ BLS_MODULUS.to_bytes32()` +pub const RETURN_VALUE: &[u8; 64] = &hex!( + "0000000000000000000000000000000000000000000000000000000000001000" + "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001" +); + +/// Run kzg point evaluation precompile. +/// +/// The Env has the KZGSettings that is needed for evaluation. +/// +/// The input is encoded as follows: +/// | versioned_hash | z | y | commitment | proof | +/// | 32 | 32 | 32 | 48 | 48 | +/// with z and y being padded 32 byte big endian values +pub fn run(input: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult { + if gas_limit < GAS_COST { + return Err(Error::OutOfGas); + } + + // Verify input length. + if input.len() != 192 { + return Err(Error::BlobInvalidInputLength); + } + + // Verify commitment matches versioned_hash + let versioned_hash = &input[..32]; + let commitment = &input[96..144]; + if kzg_to_versioned_hash(commitment) != versioned_hash { + return Err(Error::BlobMismatchedVersion); + } + + // Verify KZG proof with z and y in big endian format + let commitment = as_bytes48(commitment); + let z = as_bytes32(&input[32..64]); + let y = as_bytes32(&input[64..96]); + let proof = as_bytes48(&input[144..192]); + if !verify_kzg_proof(commitment, z, y, proof, env.cfg.kzg_settings.get()) { + return Err(Error::BlobVerifyKzgProofFailed); + } + + // Return FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded 32 byte big endian values + Ok((GAS_COST, RETURN_VALUE.into())) +} + +/// `VERSIONED_HASH_VERSION_KZG ++ sha256(commitment)[1..]` +#[inline] +pub fn kzg_to_versioned_hash(commitment: &[u8]) -> [u8; 32] { + let mut hash: [u8; 32] = Sha256::digest(commitment).into(); + hash[0] = VERSIONED_HASH_VERSION_KZG; + hash +} + +#[inline] +pub fn verify_kzg_proof( + commitment: &Bytes48, + z: &Bytes32, + y: &Bytes32, + proof: &Bytes48, + kzg_settings: &KzgSettings, +) -> bool { + KzgProof::verify_kzg_proof(commitment, z, y, proof, kzg_settings).unwrap_or(false) +} + +#[inline] +#[track_caller] +pub fn as_array(bytes: &[u8]) -> &[u8; N] { + bytes.try_into().expect("slice with incorrect length") +} + +#[inline] +#[track_caller] +pub fn as_bytes32(bytes: &[u8]) -> &Bytes32 { + // SAFETY: `#[repr(C)] Bytes32([u8; 32])` + unsafe { &*as_array::<32>(bytes).as_ptr().cast() } +} + +#[inline] +#[track_caller] +pub fn as_bytes48(bytes: &[u8]) -> &Bytes48 { + // SAFETY: `#[repr(C)] Bytes48([u8; 48])` + unsafe { &*as_array::<48>(bytes).as_ptr().cast() } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn basic_test() { + // test data from: https://github.com/ethereum/c-kzg-4844/blob/main/tests/verify_kzg_proof/kzg-mainnet/verify_kzg_proof_case_correct_proof_31ebd010e6098750/data.yaml + + let commitment = hex!("8f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7").to_vec(); + let mut versioned_hash = Sha256::digest(&commitment).to_vec(); + versioned_hash[0] = VERSIONED_HASH_VERSION_KZG; + let z = hex!("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000").to_vec(); + let y = hex!("1522a4a7f34e1ea350ae07c29c96c7e79655aa926122e95fe69fcbd932ca49e9").to_vec(); + let proof = hex!("a62ad71d14c5719385c0686f1871430475bf3a00f0aa3f7b8dd99a9abc2160744faf0070725e00b60ad9a026a15b1a8c").to_vec(); + + let input = [versioned_hash, z, y, commitment, proof].concat(); + + let expected_output = hex!("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); + let gas = 50000; + let env = Env::default(); + let (actual_gas, actual_output) = run(&input.into(), gas, &env).unwrap(); + assert_eq!(actual_gas, gas); + assert_eq!(actual_output[..], expected_output); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/src/lib.md b/docs/revm-python-spec/revm-verif/revm/precompile/src/lib.md new file mode 100644 index 00000000..0380cff1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/src/lib.md @@ -0,0 +1,274 @@ +# ๐Ÿฆ€ lib.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/src/lib.rs) + +```rust +//! # revm-precompile +//! +//! Implementations of EVM precompiled contracts. +#![warn(rustdoc::all)] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +#![deny(unused_must_use, rust_2018_idioms)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[macro_use] +#[cfg(not(feature = "std"))] +extern crate alloc as std; + +pub mod blake2; +pub mod bn128; +pub mod hash; +pub mod identity; +#[cfg(feature = "c-kzg")] +pub mod kzg_point_evaluation; +pub mod modexp; +pub mod secp256k1; +pub mod utilities; + +use core::hash::Hash; +use once_cell::race::OnceBox; +#[doc(hidden)] +pub use revm_primitives as primitives; +pub use revm_primitives::{ + precompile::{PrecompileError as Error, *}, + Address, Bytes, HashMap, Log, B256, +}; +use std::{boxed::Box, vec::Vec}; + +pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { + (len as u64 + 32 - 1) / 32 * word + base +} + +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +pub struct PrecompileOutput { + pub cost: u64, + pub output: Vec, + pub logs: Vec, +} + +impl PrecompileOutput { + pub fn without_logs(cost: u64, output: Vec) -> Self { + Self { + cost, + output, + logs: Vec::new(), + } + } +} +#[derive(Clone, Default, Debug)] +pub struct Precompiles { + /// Precompiles. + pub inner: HashMap, +} + +impl Precompiles { + /// Returns the precompiles for the given spec. + pub fn new(spec: PrecompileSpecId) -> &'static Self { + match spec { + PrecompileSpecId::HOMESTEAD => Self::homestead(), + PrecompileSpecId::BYZANTIUM => Self::byzantium(), + PrecompileSpecId::ISTANBUL => Self::istanbul(), + PrecompileSpecId::BERLIN => Self::berlin(), + PrecompileSpecId::CANCUN => Self::cancun(), + PrecompileSpecId::LATEST => Self::latest(), + } + } + + /// Returns precompiles for Homestead spec. + pub fn homestead() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Precompiles::default(); + precompiles.extend([ + secp256k1::ECRECOVER, + hash::SHA256, + hash::RIPEMD160, + identity::FUN, + ]); + Box::new(precompiles) + }) + } + + /// Returns precompiles for Byzantium spec. + pub fn byzantium() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::homestead().clone(); + precompiles.extend([ + // EIP-196: Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. + // EIP-197: Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. + bn128::add::BYZANTIUM, + bn128::mul::BYZANTIUM, + bn128::pair::BYZANTIUM, + // EIP-198: Big integer modular exponentiation. + modexp::BYZANTIUM, + ]); + Box::new(precompiles) + }) + } + + /// Returns precompiles for Istanbul spec. + pub fn istanbul() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::byzantium().clone(); + precompiles.extend([ + // EIP-152: Add BLAKE2 compression function `F` precompile. + blake2::FUN, + // EIP-1108: Reduce alt_bn128 precompile gas costs. + bn128::add::ISTANBUL, + bn128::mul::ISTANBUL, + bn128::pair::ISTANBUL, + ]); + Box::new(precompiles) + }) + } + + /// Returns precompiles for Berlin spec. + pub fn berlin() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::istanbul().clone(); + precompiles.extend([ + // EIP-2565: ModExp Gas Cost. + modexp::BERLIN, + ]); + Box::new(precompiles) + }) + } + + /// Returns precompiles for Cancun spec. + /// + /// If the `c-kzg` feature is not enabled KZG Point Evaluation precompile will not be included, + /// effectively making this the same as Berlin. + pub fn cancun() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let precompiles = Self::berlin().clone(); + + // Don't include KZG point evaluation precompile in no_std builds. + #[cfg(feature = "c-kzg")] + let precompiles = { + let mut precompiles = precompiles; + precompiles.extend([ + // EIP-4844: Shard Blob Transactions + kzg_point_evaluation::POINT_EVALUATION, + ]); + precompiles + }; + + Box::new(precompiles) + }) + } + + /// Returns the precompiles for the latest spec. + pub fn latest() -> &'static Self { + Self::cancun() + } + + /// Returns an iterator over the precompiles addresses. + #[inline] + pub fn addresses(&self) -> impl Iterator { + self.inner.keys() + } + + /// Consumes the type and returns all precompile addresses. + #[inline] + pub fn into_addresses(self) -> impl Iterator { + self.inner.into_keys() + } + + /// Is the given address a precompile. + #[inline] + pub fn contains(&self, address: &Address) -> bool { + self.inner.contains_key(address) + } + + /// Returns the precompile for the given address. + #[inline] + pub fn get(&self, address: &Address) -> Option<&Precompile> { + self.inner.get(address) + } + + /// Returns the precompile for the given address. + #[inline] + pub fn get_mut(&mut self, address: &Address) -> Option<&mut Precompile> { + self.inner.get_mut(address) + } + + /// Is the precompiles list empty. + pub fn is_empty(&self) -> bool { + self.inner.len() == 0 + } + + /// Returns the number of precompiles. + pub fn len(&self) -> usize { + self.inner.len() + } + + /// Extends the precompiles with the given precompiles. + /// + /// Other precompiles with overwrite existing precompiles. + pub fn extend(&mut self, other: impl IntoIterator) { + self.inner.extend(other.into_iter().map(Into::into)); + } +} + +#[derive(Clone, Debug)] +pub struct PrecompileWithAddress(pub Address, pub Precompile); + +impl From<(Address, Precompile)> for PrecompileWithAddress { + fn from(value: (Address, Precompile)) -> Self { + PrecompileWithAddress(value.0, value.1) + } +} + +impl From for (Address, Precompile) { + fn from(value: PrecompileWithAddress) -> Self { + (value.0, value.1) + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)] +pub enum PrecompileSpecId { + HOMESTEAD, + BYZANTIUM, + ISTANBUL, + BERLIN, + CANCUN, + LATEST, +} + +impl PrecompileSpecId { + /// Returns the appropriate precompile Spec for the primitive [SpecId](revm_primitives::SpecId) + pub const fn from_spec_id(spec_id: revm_primitives::SpecId) -> Self { + use revm_primitives::SpecId::*; + match spec_id { + FRONTIER | FRONTIER_THAWING | HOMESTEAD | DAO_FORK | TANGERINE | SPURIOUS_DRAGON => { + Self::HOMESTEAD + } + BYZANTIUM | CONSTANTINOPLE | PETERSBURG => Self::BYZANTIUM, + ISTANBUL | MUIR_GLACIER => Self::ISTANBUL, + BERLIN | LONDON | ARROW_GLACIER | GRAY_GLACIER | MERGE | SHANGHAI => Self::BERLIN, + CANCUN | PRAGUE => Self::CANCUN, + LATEST => Self::LATEST, + #[cfg(feature = "optimism")] + BEDROCK | REGOLITH | CANYON => Self::BERLIN, + #[cfg(feature = "optimism")] + ECOTONE => Self::CANCUN, + } + } +} + +/// Const function for making an address by concatenating the bytes from two given numbers. +/// +/// Note that 32 + 128 = 160 = 20 bytes (the length of an address). This function is used +/// as a convenience for specifying the addresses of the various precompiles. +#[inline] +pub const fn u64_to_address(x: u64) -> Address { + let x = x.to_be_bytes(); + Address::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], + ]) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/src/modexp.md b/docs/revm-python-spec/revm-verif/revm/precompile/src/modexp.md new file mode 100644 index 00000000..a895cca3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/src/modexp.md @@ -0,0 +1,388 @@ +# ๐Ÿฆ€ modexp.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/src/modexp.rs) + +```rust +use crate::{ + primitives::U256, + utilities::{left_pad, left_pad_vec, right_pad_vec, right_pad_with_offset}, + Error, Precompile, PrecompileResult, PrecompileWithAddress, +}; +use aurora_engine_modexp::modexp; +use core::cmp::{max, min}; +use revm_primitives::Bytes; + +pub const BYZANTIUM: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(5), + Precompile::Standard(byzantium_run), +); + +pub const BERLIN: PrecompileWithAddress = + PrecompileWithAddress(crate::u64_to_address(5), Precompile::Standard(berlin_run)); + +/// See: +/// See: +pub fn byzantium_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + run_inner(input, gas_limit, 0, |a, b, c, d| { + byzantium_gas_calc(a, b, c, d) + }) +} + +pub fn berlin_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + run_inner(input, gas_limit, 200, |a, b, c, d| { + berlin_gas_calc(a, b, c, d) + }) +} + +pub fn calculate_iteration_count(exp_length: u64, exp_highp: &U256) -> u64 { + let mut iteration_count: u64 = 0; + + if exp_length <= 32 && *exp_highp == U256::ZERO { + iteration_count = 0; + } else if exp_length <= 32 { + iteration_count = exp_highp.bit_len() as u64 - 1; + } else if exp_length > 32 { + iteration_count = (8u64.saturating_mul(exp_length - 32)) + .saturating_add(max(1, exp_highp.bit_len() as u64) - 1); + } + + max(iteration_count, 1) +} + +pub fn run_inner(input: &[u8], gas_limit: u64, min_gas: u64, calc_gas: F) -> PrecompileResult +where + F: FnOnce(u64, u64, u64, &U256) -> u64, +{ + // If there is no minimum gas, return error. + if min_gas > gas_limit { + return Err(Error::OutOfGas); + } + + // The format of input is: + // + // Where every length is a 32-byte left-padded integer representing the number of bytes + // to be taken up by the next value + const HEADER_LENGTH: usize = 96; + + // Extract the header. + let base_len = U256::from_be_bytes(right_pad_with_offset::<32>(input, 0).into_owned()); + let exp_len = U256::from_be_bytes(right_pad_with_offset::<32>(input, 32).into_owned()); + let mod_len = U256::from_be_bytes(right_pad_with_offset::<32>(input, 64).into_owned()); + + // cast base and modulus to usize, it does not make sense to handle larger values + let Ok(base_len) = usize::try_from(base_len) else { + return Err(Error::ModexpBaseOverflow); + }; + let Ok(mod_len) = usize::try_from(mod_len) else { + return Err(Error::ModexpModOverflow); + }; + + // Handle a special case when both the base and mod length are zero. + if base_len == 0 && mod_len == 0 { + return Ok((min_gas, Bytes::new())); + } + + // Cast exponent length to usize, since it does not make sense to handle larger values. + let Ok(exp_len) = usize::try_from(exp_len) else { + return Err(Error::ModexpModOverflow); + }; + + // Used to extract ADJUSTED_EXPONENT_LENGTH. + let exp_highp_len = min(exp_len, 32); + + // Throw away the header data as we already extracted lengths. + let input = input.get(HEADER_LENGTH..).unwrap_or_default(); + + let exp_highp = { + // get right padded bytes so if data.len is less then exp_len we will get right padded zeroes. + let right_padded_highp = right_pad_with_offset::<32>(input, base_len); + // If exp_len is less then 32 bytes get only exp_len bytes and do left padding. + let out = left_pad::<32>(&right_padded_highp[..exp_highp_len]); + U256::from_be_bytes(out.into_owned()) + }; + + // Check if we have enough gas. + let gas_cost = calc_gas(base_len as u64, exp_len as u64, mod_len as u64, &exp_highp); + if gas_cost > gas_limit { + return Err(Error::OutOfGas); + } + + // Padding is needed if the input does not contain all 3 values. + let input_len = base_len.saturating_add(exp_len).saturating_add(mod_len); + let input = right_pad_vec(input, input_len); + let (base, input) = input.split_at(base_len); + let (exponent, modulus) = input.split_at(exp_len); + debug_assert_eq!(modulus.len(), mod_len); + + // Call the modexp. + let output = modexp(base, exponent, modulus); + + // left pad the result to modulus length. bytes will always by less or equal to modulus length. + Ok((gas_cost, left_pad_vec(&output, mod_len).into_owned().into())) +} + +pub fn byzantium_gas_calc(base_len: u64, exp_len: u64, mod_len: u64, exp_highp: &U256) -> u64 { + // output of this function is bounded by 2^128 + fn mul_complexity(x: u64) -> U256 { + if x <= 64 { + U256::from(x * x) + } else if x <= 1_024 { + U256::from(x * x / 4 + 96 * x - 3_072) + } else { + // up-cast to avoid overflow + let x = U256::from(x); + let x_sq = x * x; // x < 2^64 => x*x < 2^128 < 2^256 (no overflow) + x_sq / U256::from(16) + U256::from(480) * x - U256::from(199_680) + } + } + + let mul = mul_complexity(core::cmp::max(mod_len, base_len)); + let iter_count = U256::from(calculate_iteration_count(exp_len, exp_highp)); + // mul * iter_count bounded by 2^195 < 2^256 (no overflow) + let gas = (mul * iter_count) / U256::from(20); + gas.saturating_to() +} + +// Calculate gas cost according to EIP 2565: +// https://eips.ethereum.org/EIPS/eip-2565 +pub fn berlin_gas_calc( + base_length: u64, + exp_length: u64, + mod_length: u64, + exp_highp: &U256, +) -> u64 { + fn calculate_multiplication_complexity(base_length: u64, mod_length: u64) -> U256 { + let max_length = max(base_length, mod_length); + let mut words = max_length / 8; + if max_length % 8 > 0 { + words += 1; + } + let words = U256::from(words); + words * words + } + + let multiplication_complexity = calculate_multiplication_complexity(base_length, mod_length); + let iteration_count = calculate_iteration_count(exp_length, exp_highp); + let gas = (multiplication_complexity * U256::from(iteration_count)) / U256::from(3); + max(200, gas.saturating_to()) +} + +#[cfg(test)] +mod tests { + use super::*; + use revm_primitives::hex; + use std::vec::Vec; + + struct Test { + input: &'static str, + expected: &'static str, + name: &'static str, + } + + const TESTS: [Test; 19] = [ + Test { + input: "\ + 0000000000000000000000000000000000000000000000000000000000000064\ + 0000000000000000000000000000000000000000000000000000000000000064\ + 0000000000000000000000000000000000000000000000000000000000000064\ + 5442ddc2b70f66c1f6d2b296c0a875be7eddd0a80958cbc7425f1899ccf90511\ + a5c318226e48ee23f130b44dc17a691ce66be5da18b85ed7943535b205aa125e\ + 9f59294a00f05155c23e97dac6b3a00b0c63c8411bf815fc183b420b4d9dc5f7\ + 15040d5c60957f52d334b843197adec58c131c907cd96059fc5adce9dda351b5\ + df3d666fcf3eb63c46851c1816e323f2119ebdf5ef35", + expected: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + name: "eth_tests_modexp_modsize0_returndatasizeFiller", + }, + Test { + input: "\ + 0000000000000000000000000000000000000000000000000000000000000001\ + 0000000000000000000000000000000000000000000000000000000000000020\ + 0000000000000000000000000000000000000000000000000000000000000020\ + 03\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e\ + ffffffffffffffffffffffffffffffffffffffffff2f", + expected: "162ead82cadefaeaf6e9283248fdf2f2845f6396f6f17c4d5a39f820b6f6b5f9", + name: "eth_tests_create2callPrecompiles_test0_berlin", + }, + Test { + input: "\ + 0000000000000000000000000000000000000000000000000000000000000001\ + 0000000000000000000000000000000000000000000000000000000000000020\ + 0000000000000000000000000000000000000000000000000000000000000020\ + 03\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "eip198_example_1", + }, + Test { + input: "\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000020\ + 0000000000000000000000000000000000000000000000000000000000000020\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: "0000000000000000000000000000000000000000000000000000000000000000", + name: "eip198_example_2", + }, + Test { + input: "\ + 0000000000000000000000000000000000000000000000000000000000000040\ + 0000000000000000000000000000000000000000000000000000000000000001\ + 0000000000000000000000000000000000000000000000000000000000000040\ + e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb003\ + 3ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5\ + 02fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac\ + 2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c\ + 6b", + expected: "60008f1614cc01dcfb6bfb09c625cf90b47d4468db81b5f8b7a39d42f332eab9b2da8f2d95311648a8f243f4bb13cfb3d8f7f2a3c014122ebb3ed41b02783adc", + name: "nagydani_1_square", + }, + Test { + input: "\ + 0000000000000000000000000000000000000000000000000000000000000040\ + 0000000000000000000000000000000000000000000000000000000000000001\ + 0000000000000000000000000000000000000000000000000000000000000040\ + e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb003\ + 3ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5\ + 03fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac\ + 2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c\ + 6b", + expected: "4834a46ba565db27903b1c720c9d593e84e4cbd6ad2e64b31885d944f68cd801f92225a8961c952ddf2797fa4701b330c85c4b363798100b921a1a22a46a7fec", + name: "nagydani_1_qube" + }, + Test { + input: "\ + 0000000000000000000000000000000000000000000000000000000000000040\ + 0000000000000000000000000000000000000000000000000000000000000003\ + 0000000000000000000000000000000000000000000000000000000000000040\ + e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb003\ + 3ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5\ + 010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd60\ + 95ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a\ + 248c6b", + expected: "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2", + name: "nagydani_1_pow0x10001", + }, + Test { + input: "\ + 0000000000000000000000000000000000000000000000000000000000000080\ + 0000000000000000000000000000000000000000000000000000000000000001\ + 0000000000000000000000000000000000000000000000000000000000000080\ + cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be\ + 0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81\ + dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dc\ + b9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51\ + 02e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3\ + ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b2\ + 8c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be\ + 9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c2870\ + 87", + expected: "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70", + name: "nagydani_2_square", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", + expected: "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f", + name: "nagydani_2_qube", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", + expected: "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2", + name: "nagydani_2_pow0x10001", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", + expected: "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8", + name: "nagydani_3_square", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", + expected: "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e", + name: "nagydani_3_qube", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", + expected: "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76", + name: "nagydani_3_pow0x10001", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", + expected: "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10", + name: "nagydani_4_square", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", + expected: "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc", + name: "nagydani_4_qube", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", + expected: "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963", + name: "nagydani_4_pow0x10001", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", + expected: "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb", + name: "nagydani_5_square", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", + expected: "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f", + name: "nagydani_5_qube", + }, + Test { + input: "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", + expected: "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500", + name: "nagydani_5_pow0x10001", + } + ]; + + const BYZANTIUM_GAS: [u64; 19] = [ + 360_217, 13_056, 13_056, 13_056, 204, 204, 3_276, 665, 665, 10_649, 1_894, 1_894, 30_310, + 5_580, 5_580, 89_292, 17_868, 17_868, 285_900, + ]; + + const BERLIN_GAS: [u64; 19] = [ + 44_954, 1_360, 1_360, 1_360, 200, 200, 341, 200, 200, 1_365, 341, 341, 5_461, 1_365, 1_365, + 21_845, 5_461, 5_461, 87_381, + ]; + + #[test] + fn test_byzantium_modexp_gas() { + for (test, &test_gas) in TESTS.iter().zip(BYZANTIUM_GAS.iter()) { + let input = hex::decode(test.input).unwrap().into(); + let res = byzantium_run(&input, 100_000_000).unwrap(); + let expected = hex::decode(test.expected).unwrap(); + assert_eq!( + res.0, test_gas, + "used gas not matching for test: {}", + test.name + ); + assert_eq!(res.1, expected, "test:{}", test.name); + } + } + + #[test] + fn test_berlin_modexp_gas() { + for (test, &test_gas) in TESTS.iter().zip(BERLIN_GAS.iter()) { + let input = hex::decode(test.input).unwrap().into(); + let res = berlin_run(&input, 100_000_000).unwrap(); + let expected = hex::decode(test.expected).unwrap(); + assert_eq!( + res.0, test_gas, + "used gas not matching for test: {}", + test.name + ); + assert_eq!(res.1, expected, "test:{}", test.name); + } + } + + #[test] + fn test_berlin_modexp_empty_input() { + let res = berlin_run(&Bytes::new(), 100_000).unwrap(); + let expected: Vec = Vec::new(); + assert_eq!(res.1, expected) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/src/secp256k1.md b/docs/revm-python-spec/revm-verif/revm/precompile/src/secp256k1.md new file mode 100644 index 00000000..13789e8d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/src/secp256k1.md @@ -0,0 +1,97 @@ +# ๐Ÿฆ€ secp256k1.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/src/secp256k1.rs) + +```rust +use crate::{utilities::right_pad, Error, Precompile, PrecompileResult, PrecompileWithAddress}; +use revm_primitives::{alloy_primitives::B512, Bytes, B256}; + +pub const ECRECOVER: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(1), + Precompile::Standard(ec_recover_run), +); + +pub use self::secp256k1::ecrecover; + +#[cfg(not(feature = "secp256k1"))] +#[allow(clippy::module_inception)] +mod secp256k1 { + use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; + use revm_primitives::{alloy_primitives::B512, keccak256, B256}; + + pub fn ecrecover(sig: &B512, mut recid: u8, msg: &B256) -> Result { + // parse signature + let mut sig = Signature::from_slice(sig.as_slice())?; + + // normalize signature and flip recovery id if needed. + if let Some(sig_normalized) = sig.normalize_s() { + sig = sig_normalized; + recid ^= 1; + } + let recid = RecoveryId::from_byte(recid).expect("recovery ID is valid"); + + // recover key + let recovered_key = VerifyingKey::recover_from_prehash(&msg[..], &sig, recid)?; + // hash it + let mut hash = keccak256( + &recovered_key + .to_encoded_point(/* compress = */ false) + .as_bytes()[1..], + ); + + // truncate to 20 bytes + hash[..12].fill(0); + Ok(hash) + } +} + +#[cfg(feature = "secp256k1")] +#[allow(clippy::module_inception)] +mod secp256k1 { + use revm_primitives::{alloy_primitives::B512, keccak256, B256}; + use secp256k1::{ + ecdsa::{RecoverableSignature, RecoveryId}, + Message, Secp256k1, + }; + + // Silence the unused crate dependency warning. + use k256 as _; + + pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { + let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); + let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; + + let secp = Secp256k1::new(); + let msg = Message::from_digest(msg.0); + let public = secp.recover_ecdsa(&msg, &sig)?; + + let mut hash = keccak256(&public.serialize_uncompressed()[1..]); + hash[..12].fill(0); + Ok(hash) + } +} + +pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + const ECRECOVER_BASE: u64 = 3_000; + + if ECRECOVER_BASE > gas_limit { + return Err(Error::OutOfGas); + } + + let input = right_pad::<128>(input); + + // `v` must be a 32-byte big-endian integer equal to 27 or 28. + if !(input[32..63].iter().all(|&b| b == 0) && matches!(input[63], 27 | 28)) { + return Ok((ECRECOVER_BASE, Bytes::new())); + } + + let msg = <&B256>::try_from(&input[0..32]).unwrap(); + let recid = input[63] - 27; + let sig = <&B512>::try_from(&input[64..128]).unwrap(); + + let out = secp256k1::ecrecover(sig, recid, msg) + .map(|o| o.to_vec().into()) + .unwrap_or_default(); + Ok((ECRECOVER_BASE, out)) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/precompile/src/utilities.md b/docs/revm-python-spec/revm-verif/revm/precompile/src/utilities.md new file mode 100644 index 00000000..42f1ed66 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/precompile/src/utilities.md @@ -0,0 +1,182 @@ +# ๐Ÿฆ€ utilities.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/precompile/src/utilities.rs) + +```rust +use revm_primitives::{b256, Bytes, B256}; +use std::borrow::Cow; + +/// Right-pads the given slice at `offset` with zeroes until `LEN`. +/// +/// Returns the first `LEN` bytes if it does not need padding. +#[inline] +pub fn right_pad_with_offset(data: &[u8], offset: usize) -> Cow<'_, [u8; LEN]> { + right_pad(data.get(offset..).unwrap_or_default()) +} + +/// Right-pads the given slice at `offset` with zeroes until `len`. +/// +/// Returns the first `len` bytes if it does not need padding. +#[inline] +pub fn right_pad_with_offset_vec(data: &[u8], offset: usize, len: usize) -> Cow<'_, [u8]> { + right_pad_vec(data.get(offset..).unwrap_or_default(), len) +} + +/// Right-pads the given slice with zeroes until `LEN`. +/// +/// Returns the first `LEN` bytes if it does not need padding. +#[inline] +pub fn right_pad(data: &[u8]) -> Cow<'_, [u8; LEN]> { + if let Some(data) = data.get(..LEN) { + Cow::Borrowed(data.try_into().unwrap()) + } else { + let mut padded = [0; LEN]; + padded[..data.len()].copy_from_slice(data); + Cow::Owned(padded) + } +} + +/// Right-pads the given slice with zeroes until `len`. +/// +/// Returns the first `len` bytes if it does not need padding. +#[inline] +pub fn right_pad_vec(data: &[u8], len: usize) -> Cow<'_, [u8]> { + if let Some(data) = data.get(..len) { + Cow::Borrowed(data) + } else { + let mut padded = vec![0; len]; + padded[..data.len()].copy_from_slice(data); + Cow::Owned(padded) + } +} + +/// Left-pads the given slice with zeroes until `LEN`. +/// +/// Returns the first `LEN` bytes if it does not need padding. +#[inline] +pub fn left_pad(data: &[u8]) -> Cow<'_, [u8; LEN]> { + if let Some(data) = data.get(..LEN) { + Cow::Borrowed(data.try_into().unwrap()) + } else { + let mut padded = [0; LEN]; + padded[LEN - data.len()..].copy_from_slice(data); + Cow::Owned(padded) + } +} + +/// Left-pads the given slice with zeroes until `len`. +/// +/// Returns the first `len` bytes if it does not need padding. +#[inline] +pub fn left_pad_vec(data: &[u8], len: usize) -> Cow<'_, [u8]> { + if let Some(data) = data.get(..len) { + Cow::Borrowed(data) + } else { + let mut padded = vec![0; len]; + padded[len - data.len()..].copy_from_slice(data); + Cow::Owned(padded) + } +} + +/// Converts a boolean to a left-padded 32-byte `Bytes` value. +/// +/// This is optimized to not allocate at runtime by using 2 static arrays. +#[inline] +pub const fn bool_to_bytes32(value: bool) -> Bytes { + Bytes::from_static(&bool_to_b256(value).0) +} + +/// Converts a boolean to a left-padded `B256` value. +/// +/// This is optimized to not allocate at runtime by using 2 static arrays. +#[inline] +pub const fn bool_to_b256(value: bool) -> &'static B256 { + const TRUE: &B256 = &b256!("0000000000000000000000000000000000000000000000000000000000000001"); + const FALSE: &B256 = &b256!("0000000000000000000000000000000000000000000000000000000000000000"); + if value { + TRUE + } else { + FALSE + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn get_with_right_padding() { + let data = [1, 2, 3, 4]; + let padded = right_pad_with_offset::<8>(&data, 4); + assert!(matches!(padded, Cow::Owned(_))); + assert_eq!(padded[..], [0, 0, 0, 0, 0, 0, 0, 0]); + let padded = right_pad_with_offset_vec(&data, 4, 8); + assert!(matches!(padded, Cow::Owned(_))); + assert_eq!(padded[..], [0, 0, 0, 0, 0, 0, 0, 0]); + + let data = [1, 2, 3, 4, 5, 6, 7, 8]; + let padded = right_pad_with_offset::<8>(&data, 0); + assert!(matches!(padded, Cow::Borrowed(_))); + assert_eq!(padded[..], [1, 2, 3, 4, 5, 6, 7, 8]); + let padded = right_pad_with_offset_vec(&data, 0, 8); + assert!(matches!(padded, Cow::Borrowed(_))); + assert_eq!(padded[..], [1, 2, 3, 4, 5, 6, 7, 8]); + + let data = [1, 2, 3, 4, 5, 6, 7, 8]; + let padded = right_pad_with_offset::<8>(&data, 4); + assert!(matches!(padded, Cow::Owned(_))); + assert_eq!(padded[..], [5, 6, 7, 8, 0, 0, 0, 0]); + let padded = right_pad_with_offset_vec(&data, 4, 8); + assert!(matches!(padded, Cow::Owned(_))); + assert_eq!(padded[..], [5, 6, 7, 8, 0, 0, 0, 0]); + } + + #[test] + fn right_padding() { + let data = [1, 2, 3, 4]; + let padded = right_pad::<8>(&data); + assert!(matches!(padded, Cow::Owned(_))); + assert_eq!(padded[..], [1, 2, 3, 4, 0, 0, 0, 0]); + let padded = right_pad_vec(&data, 8); + assert!(matches!(padded, Cow::Owned(_))); + assert_eq!(padded[..], [1, 2, 3, 4, 0, 0, 0, 0]); + + let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let padded = right_pad::<8>(&data); + assert!(matches!(padded, Cow::Borrowed(_))); + assert_eq!(padded[..], [1, 2, 3, 4, 5, 6, 7, 8]); + let padded = right_pad_vec(&data, 8); + assert!(matches!(padded, Cow::Borrowed(_))); + assert_eq!(padded[..], [1, 2, 3, 4, 5, 6, 7, 8]); + } + + #[test] + fn left_padding() { + let data = [1, 2, 3, 4]; + let padded = left_pad::<8>(&data); + assert!(matches!(padded, Cow::Owned(_))); + assert_eq!(padded[..], [0, 0, 0, 0, 1, 2, 3, 4]); + let padded = left_pad_vec(&data, 8); + assert!(matches!(padded, Cow::Owned(_))); + assert_eq!(padded[..], [0, 0, 0, 0, 1, 2, 3, 4]); + + let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let padded = left_pad::<8>(&data); + assert!(matches!(padded, Cow::Borrowed(_))); + assert_eq!(padded[..], [1, 2, 3, 4, 5, 6, 7, 8]); + let padded = left_pad_vec(&data, 8); + assert!(matches!(padded, Cow::Borrowed(_))); + assert_eq!(padded[..], [1, 2, 3, 4, 5, 6, 7, 8]); + } + + #[test] + fn bool2bytes() { + let f = bool_to_bytes32(false); + assert_eq!(f[..], [0; 32]); + let t = bool_to_bytes32(true); + assert_eq!(t.len(), 32); + assert_eq!(t[..31], [0; 31]); + assert_eq!(t[31], 1); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode.md new file mode 100644 index 00000000..2b8f71ae --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode.md @@ -0,0 +1,154 @@ +# ๐Ÿฆ€ bytecode.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/bytecode.rs) + +```rust +pub mod eof; +pub mod legacy; + +pub use eof::Eof; +pub use legacy::{JumpTable, LegacyAnalyzedBytecode}; + +use crate::{keccak256, Bytes, B256, KECCAK_EMPTY}; + +/// State of the [`Bytecode`] analysis. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum Bytecode { + /// No analysis has been performed. + LegacyRaw(Bytes), + /// The bytecode has been analyzed for valid jump destinations. + LegacyAnalyzed(LegacyAnalyzedBytecode), + /// Ethereum Object Format + Eof(Eof), +} + +impl Default for Bytecode { + #[inline] + fn default() -> Self { + // Creates a new legacy analyzed [`Bytecode`] with exactly one STOP opcode. + Self::new() + } +} + +impl Bytecode { + // Creates a new legacy analyzed [`Bytecode`] with exactly one STOP opcode. + #[inline] + pub fn new() -> Self { + Self::LegacyAnalyzed(LegacyAnalyzedBytecode::default()) + } + + /// Return jump table if bytecode is analyzed + #[inline] + pub fn legacy_jump_table(&self) -> Option<&JumpTable> { + match &self { + Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()), + _ => None, + } + } + + /// Calculate hash of the bytecode. + pub fn hash_slow(&self) -> B256 { + if self.is_empty() { + KECCAK_EMPTY + } else { + keccak256(self.original_byte_slice()) + } + } + + /// Return reference to the EOF if bytecode is EOF. + #[inline] + pub const fn eof(&self) -> Option<&Eof> { + match self { + Self::Eof(eof) => Some(eof), + _ => None, + } + } + + /// Return true if bytecode is EOF. + #[inline] + pub const fn is_eof(&self) -> bool { + matches!(self, Self::Eof(_)) + } + + /// Creates a new raw [`Bytecode`]. + #[inline] + pub fn new_raw(bytecode: Bytes) -> Self { + Self::LegacyRaw(bytecode) + } + + /// Create new checked bytecode. + /// + /// # Safety + /// + /// Bytecode needs to end with STOP (0x00) opcode as checked bytecode assumes + /// that it is safe to iterate over bytecode without checking lengths. + pub unsafe fn new_analyzed( + bytecode: Bytes, + original_len: usize, + jump_table: JumpTable, + ) -> Self { + Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new( + bytecode, + original_len, + jump_table, + )) + } + + /// Returns a reference to the bytecode. + /// + /// In case of EOF this will be the first code section. + #[inline] + pub fn bytecode(&self) -> &Bytes { + match self { + Self::LegacyRaw(bytes) => bytes, + Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(), + Self::Eof(eof) => eof + .body + .code(0) + .expect("Valid EOF has at least one code section"), + } + } + + /// Returns false if bytecode can't be executed in Interpreter. + pub fn is_execution_ready(&self) -> bool { + !matches!(self, Self::LegacyRaw(_)) + } + + /// Returns a reference to the original bytecode. + #[inline] + pub fn original_bytes(&self) -> Bytes { + match self { + Self::LegacyRaw(bytes) => bytes.clone(), + Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(), + Self::Eof(eof) => eof.raw().clone(), + } + } + + /// Returns the original bytecode as a byte slice. + #[inline] + pub fn original_byte_slice(&self) -> &[u8] { + match self { + Self::LegacyRaw(bytes) => bytes, + Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(), + Self::Eof(eof) => eof.raw(), + } + } + + /// Returns the length of the raw bytes. + #[inline] + pub fn len(&self) -> usize { + match self { + Self::LegacyRaw(bytes) => bytes.len(), + Self::LegacyAnalyzed(analyzed) => analyzed.original_len(), + Self::Eof(eof) => eof.size(), + } + } + + /// Returns whether the bytecode is empty. + #[inline] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof.md new file mode 100644 index 00000000..62005588 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof.md @@ -0,0 +1,162 @@ +# ๐Ÿฆ€ eof.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/bytecode/eof.rs) + +```rust +mod body; +mod decode_helpers; +mod header; +mod types_section; + +pub use body::EofBody; +pub use header::EofHeader; +pub use types_section::TypesSection; + +use crate::Bytes; +use core::cmp::min; +use std::{vec, vec::Vec}; + +/// EOF - Ethereum Object Format. +/// +/// It consist of a header, body and raw original bytes Specified in EIP. +/// Most of body contain Bytes so it references to the raw bytes. +/// +/// If there is a need to create new EOF from scratch, it is recommended to use `EofBody` and +/// use `encode` function to create full [`Eof`] object. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Eof { + pub header: EofHeader, + pub body: EofBody, + pub raw: Bytes, +} + +impl Default for Eof { + fn default() -> Self { + let body = EofBody { + // types section with zero inputs, zero outputs and zero max stack size. + types_section: vec![TypesSection::default()], + // One code section with a STOP byte. + code_section: vec![[0x00].into()], + container_section: vec![], + data_section: Bytes::new(), + is_data_filled: true, + }; + body.into_eof() + } +} + +impl Eof { + /// Returns len of the header and body in bytes. + pub fn size(&self) -> usize { + self.header.size() + self.header.body_size() + } + + /// Return raw EOF bytes. + pub fn raw(&self) -> &Bytes { + &self.raw + } + + /// Returns a slice of the raw bytes. + /// If offset is greater than the length of the raw bytes, an empty slice is returned. + /// If len is greater than the length of the raw bytes, the slice is truncated to the length of the raw bytes. + pub fn data_slice(&self, offset: usize, len: usize) -> &[u8] { + self.body + .data_section + .get(offset..) + .and_then(|bytes| bytes.get(..min(len, bytes.len()))) + .unwrap_or(&[]) + } + + /// Returns a slice of the data section. + pub fn data(&self) -> &[u8] { + &self.body.data_section + } + + /// Slow encode EOF bytes. + pub fn encode_slow(&self) -> Bytes { + let mut buffer: Vec = Vec::with_capacity(self.size()); + self.header.encode(&mut buffer); + self.body.encode(&mut buffer); + buffer.into() + } + + /// Decode EOF from raw bytes. + pub fn decode(raw: Bytes) -> Result { + let (header, _) = EofHeader::decode(&raw)?; + let body = EofBody::decode(&raw, &header)?; + Ok(Self { header, body, raw }) + } +} + +/// EOF decode errors. +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +pub enum EofDecodeError { + /// Short input while processing EOF. + MissingInput, + /// Short body while processing EOF. + MissingBodyWithoutData, + /// Body size is more than specified in the header. + DanglingData, + /// Invalid types section data. + InvalidTypesSection, + /// Invalid types section size. + InvalidTypesSectionSize, + /// Invalid EOF magic number. + InvalidEOFMagicNumber, + /// Invalid EOF version. + InvalidEOFVersion, + /// Invalid number for types kind + InvalidTypesKind, + /// Invalid number for code kind + InvalidCodeKind, + /// Invalid terminal code + InvalidTerminalByte, + /// Invalid data kind + InvalidDataKind, + /// Invalid kind after code + InvalidKindAfterCode, + /// Mismatch of code and types sizes. + MismatchCodeAndTypesSize, + /// There should be at least one size. + NonSizes, + /// Missing size. + ShortInputForSizes, + /// Size cant be zero + ZeroSize, + /// Invalid code number. + TooManyCodeSections, + /// Invalid number of code sections. + ZeroCodeSections, + /// Invalid container number. + TooManyContainerSections, +} + +#[cfg(test)] +mod test { + + use super::*; + use crate::bytes; + + #[test] + fn decode_eof() { + let bytes = bytes!("ef000101000402000100010400000000800000fe"); + let eof = Eof::decode(bytes.clone()).unwrap(); + assert_eq!(bytes, eof.encode_slow()); + } + + #[test] + fn data_slice() { + let bytes = bytes!("ef000101000402000100010400000000800000fe"); + let mut eof = Eof::decode(bytes.clone()).unwrap(); + eof.body.data_section = bytes!("01020304"); + assert_eq!(eof.data_slice(0, 1), &[0x01]); + assert_eq!(eof.data_slice(0, 4), &[0x01, 0x02, 0x03, 0x04]); + assert_eq!(eof.data_slice(0, 5), &[0x01, 0x02, 0x03, 0x04]); + assert_eq!(eof.data_slice(1, 2), &[0x02, 0x03]); + assert_eq!(eof.data_slice(10, 2), &[]); + assert_eq!(eof.data_slice(1, 0), &[]); + assert_eq!(eof.data_slice(10, 0), &[]); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/body.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/body.md new file mode 100644 index 00000000..bd55fe67 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/body.md @@ -0,0 +1,115 @@ +# ๐Ÿฆ€ body.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/bytecode/eof/body.rs) + +```rust +use super::{Eof, EofDecodeError, EofHeader, TypesSection}; +use crate::Bytes; +use std::vec::Vec; + +/// EOF Body, contains types, code, container and data sections. +/// +/// Can be used to create new EOF object. +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct EofBody { + pub types_section: Vec, + pub code_section: Vec, + pub container_section: Vec, + pub data_section: Bytes, + pub is_data_filled: bool, +} + +impl EofBody { + // Get code section + pub fn code(&self, index: usize) -> Option<&Bytes> { + self.code_section.get(index) + } + + /// Create EOF from body. + pub fn into_eof(self) -> Eof { + // TODO add bounds checks. + let header = EofHeader { + types_size: self.types_section.len() as u16 * 4, + code_sizes: self.code_section.iter().map(|x| x.len() as u16).collect(), + container_sizes: self + .container_section + .iter() + .map(|x| x.len() as u16) + .collect(), + data_size: self.data_section.len() as u16, + sum_code_sizes: self.code_section.iter().map(|x| x.len()).sum(), + sum_container_sizes: self.container_section.iter().map(|x| x.len()).sum(), + }; + let mut buffer = Vec::new(); + header.encode(&mut buffer); + self.encode(&mut buffer); + Eof { + header, + body: self, + raw: buffer.into(), + } + } + + /// Encode Body into buffer. + pub fn encode(&self, buffer: &mut Vec) { + for types_section in &self.types_section { + types_section.encode(buffer); + } + + for code_section in &self.code_section { + buffer.extend_from_slice(code_section); + } + + for container_section in &self.container_section { + buffer.extend_from_slice(container_section); + } + + buffer.extend_from_slice(&self.data_section); + } + + /// Decode EOF body from buffer and Header. + pub fn decode(input: &Bytes, header: &EofHeader) -> Result { + let header_len = header.size(); + let partial_body_len = + header.sum_code_sizes + header.sum_container_sizes + header.types_size as usize; + let full_body_len = partial_body_len + header.data_size as usize; + + if input.len() < header_len + partial_body_len { + return Err(EofDecodeError::MissingBodyWithoutData); + } + + if input.len() > header_len + full_body_len { + return Err(EofDecodeError::DanglingData); + } + + let mut body = EofBody::default(); + + let mut types_input = &input[header_len..]; + for _ in 0..header.types_count() { + let (types_section, local_input) = TypesSection::decode(types_input)?; + types_input = local_input; + body.types_section.push(types_section); + } + + // extract code section + let mut start = header_len + header.types_size as usize; + for size in header.code_sizes.iter().map(|x| *x as usize) { + body.code_section.push(input.slice(start..start + size)); + start += size; + } + + // extract container section + for size in header.container_sizes.iter().map(|x| *x as usize) { + body.container_section + .push(input.slice(start..start + size)); + start += size; + } + + body.data_section = input.slice(start..); + body.is_data_filled = body.data_section.len() == header.data_size as usize; + + Ok(body) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/decode_helpers.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/decode_helpers.md new file mode 100644 index 00000000..71347e03 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/decode_helpers.md @@ -0,0 +1,26 @@ +# ๐Ÿฆ€ decode_helpers.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/bytecode/eof/decode_helpers.rs) + +```rust +use super::EofDecodeError; + +/// Consumes a u8 from the input. +#[inline] +pub(crate) fn consume_u8(input: &[u8]) -> Result<(&[u8], u8), EofDecodeError> { + if input.is_empty() { + return Err(EofDecodeError::MissingInput); + } + Ok((&input[1..], input[0])) +} + +/// Consumes a u16 from the input. +#[inline] +pub(crate) fn consume_u16(input: &[u8]) -> Result<(&[u8], u16), EofDecodeError> { + if input.len() < 2 { + return Err(EofDecodeError::MissingInput); + } + let (int_bytes, rest) = input.split_at(2); + Ok((rest, u16::from_be_bytes([int_bytes[0], int_bytes[1]]))) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/header.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/header.md new file mode 100644 index 00000000..59fa0c5f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/header.md @@ -0,0 +1,263 @@ +# ๐Ÿฆ€ header.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/bytecode/eof/header.rs) + +```rust +use super::{ + decode_helpers::{consume_u16, consume_u8}, + EofDecodeError, +}; +use std::vec::Vec; + +/// EOF Header containing +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct EofHeader { + /// Size of EOF types section. + /// types section includes num of input and outputs and max stack size. + pub types_size: u16, + /// Sizes of EOF code section. + /// Code size can't be zero. + pub code_sizes: Vec, + /// EOF Container size. + /// Container size can be zero. + pub container_sizes: Vec, + /// EOF data size. + pub data_size: u16, + /// sum code sizes + pub sum_code_sizes: usize, + /// sum container sizes + pub sum_container_sizes: usize, +} + +const KIND_TERMINAL: u8 = 0; +const KIND_TYPES: u8 = 1; +const KIND_CODE: u8 = 2; +const KIND_CONTAINER: u8 = 3; +const KIND_DATA: u8 = 4; + +#[inline] +fn consume_header_section_size(input: &[u8]) -> Result<(&[u8], Vec, usize), EofDecodeError> { + // num_sections 2 bytes 0x0001-0xFFFF + // 16-bit unsigned big-endian integer denoting the number of the sections + let (input, num_sections) = consume_u16(input)?; + if num_sections == 0 { + return Err(EofDecodeError::NonSizes); + } + let byte_size = (num_sections * 2) as usize; + if input.len() < byte_size { + return Err(EofDecodeError::ShortInputForSizes); + } + let mut sizes = Vec::with_capacity(num_sections as usize); + let mut sum = 0; + for i in 0..num_sections as usize { + // size 2 bytes 0x0001-0xFFFF + // 16-bit unsigned big-endian integer denoting the length of the section content + let code_size = u16::from_be_bytes([input[i * 2], input[i * 2 + 1]]); + if code_size == 0 { + return Err(EofDecodeError::ZeroSize); + } + sum += code_size as usize; + sizes.push(code_size); + } + + Ok((&input[byte_size..], sizes, sum)) +} + +impl EofHeader { + /// Length of the header in bytes. + /// + /// Length is calculated as: + /// magic 2 byte + + /// version 1 byte + + /// types section 3 bytes + + /// code section 3 bytes + + /// num_code_sections * 2 + + /// if num_container_sections != 0 { container section 3 bytes} + + /// num_container_sections * 2 + + /// data section 3 bytes + + /// terminator 1 byte + /// + /// It is minimum 15 bytes (there is at least one code section). + pub fn size(&self) -> usize { + let optional_container_sizes = if self.container_sizes.is_empty() { + 0 + } else { + 3 + self.container_sizes.len() * 2 + }; + 13 + self.code_sizes.len() * 2 + optional_container_sizes + } + + /// Returns number of types. + pub fn types_count(&self) -> usize { + self.types_size as usize / 4 + } + + /// Returns body size. It is sum of code sizes, container sizes and data size. + pub fn body_size(&self) -> usize { + self.sum_code_sizes + self.sum_container_sizes + self.data_size as usize + } + + /// Returns raw size of the EOF. + pub fn eof_size(&self) -> usize { + self.size() + self.body_size() + } + + /// Encodes EOF header into binary form. + pub fn encode(&self, buffer: &mut Vec) { + // magic 2 bytes 0xEF00 EOF prefix + buffer.extend_from_slice(&0xEF00u16.to_be_bytes()); + // version 1 byte 0x01 EOF version + buffer.push(0x01); + // kind_types 1 byte 0x01 kind marker for types size section + buffer.push(KIND_TYPES); + // types_size 2 bytes 0x0004-0xFFFF + buffer.extend_from_slice(&self.types_size.to_be_bytes()); + // kind_code 1 byte 0x02 kind marker for code size section + buffer.push(KIND_CODE); + // code_sections_sizes + buffer.extend_from_slice(&(self.code_sizes.len() as u16).to_be_bytes()); + for size in &self.code_sizes { + buffer.extend_from_slice(&size.to_be_bytes()); + } + // kind_container_or_data 1 byte 0x03 or 0x04 kind marker for container size section or data size section + if self.container_sizes.is_empty() { + buffer.push(KIND_DATA); + } else { + buffer.push(KIND_CONTAINER); + // container_sections_sizes + buffer.extend_from_slice(&(self.container_sizes.len() as u16).to_be_bytes()); + for size in &self.container_sizes { + buffer.extend_from_slice(&size.to_be_bytes()); + } + // kind_data 1 byte 0x04 kind marker for data size section + buffer.push(KIND_DATA); + } + // data_size 2 bytes 0x0000-0xFFFF 16-bit unsigned big-endian integer denoting the length of the data section content + buffer.extend_from_slice(&self.data_size.to_be_bytes()); + // terminator 1 byte 0x00 marks the end of the EofHeader + buffer.push(KIND_TERMINAL); + } + + /// Decodes EOF header from binary form. + pub fn decode(input: &[u8]) -> Result<(Self, &[u8]), EofDecodeError> { + let mut header = EofHeader::default(); + + // magic 2 bytes 0xEF00 EOF prefix + let (input, kind) = consume_u16(input)?; + if kind != 0xEF00 { + return Err(EofDecodeError::InvalidEOFMagicNumber); + } + + // version 1 byte 0x01 EOF version + let (input, version) = consume_u8(input)?; + if version != 0x01 { + return Err(EofDecodeError::InvalidEOFVersion); + } + + // kind_types 1 byte 0x01 kind marker for types size section + let (input, kind_types) = consume_u8(input)?; + if kind_types != KIND_TYPES { + return Err(EofDecodeError::InvalidTypesKind); + } + + // types_size 2 bytes 0x0004-0xFFFF + // 16-bit unsigned big-endian integer denoting the length of the type section content + let (input, types_size) = consume_u16(input)?; + header.types_size = types_size; + + if header.types_size % 4 != 0 { + return Err(EofDecodeError::InvalidTypesSection); + } + + // kind_code 1 byte 0x02 kind marker for code size section + let (input, kind_types) = consume_u8(input)?; + if kind_types != KIND_CODE { + return Err(EofDecodeError::InvalidCodeKind); + } + + // code_sections_sizes + let (input, sizes, sum) = consume_header_section_size(input)?; + + if sizes.len() > 1024 { + return Err(EofDecodeError::TooManyCodeSections); + } + + if sizes.is_empty() { + return Err(EofDecodeError::ZeroCodeSections); + } + + if sizes.len() != (types_size / 4) as usize { + return Err(EofDecodeError::MismatchCodeAndTypesSize); + } + + header.code_sizes = sizes; + header.sum_code_sizes = sum; + + let (input, kind_container_or_data) = consume_u8(input)?; + + let input = match kind_container_or_data { + KIND_CONTAINER => { + // container_sections_sizes + let (input, sizes, sum) = consume_header_section_size(input)?; + // the number of container sections must not exceed 256 + if sizes.len() > 256 { + return Err(EofDecodeError::TooManyContainerSections); + } + header.container_sizes = sizes; + header.sum_container_sizes = sum; + let (input, kind_data) = consume_u8(input)?; + if kind_data != KIND_DATA { + return Err(EofDecodeError::InvalidDataKind); + } + input + } + KIND_DATA => input, + _ => return Err(EofDecodeError::InvalidKindAfterCode), + }; + + // data_size 2 bytes 0x0000-0xFFFF 16-bit + // unsigned big-endian integer denoting the length + // of the data section content (for not yet deployed + // containers this can be more than the actual content, see Data Section Lifecycle) + let (input, data_size) = consume_u16(input)?; + header.data_size = data_size; + + // terminator 1 byte 0x00 marks the end of the EofHeader + let (input, terminator) = consume_u8(input)?; + if terminator != KIND_TERMINAL { + return Err(EofDecodeError::InvalidTerminalByte); + } + + Ok((header, input)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::hex; + + #[test] + fn sanity_header_decode() { + let input = hex!("ef000101000402000100010400000000800000fe"); + let (header, _) = EofHeader::decode(&input).unwrap(); + assert_eq!(header.types_size, 4); + assert_eq!(header.code_sizes, vec![1]); + assert_eq!(header.container_sizes, vec![]); + assert_eq!(header.data_size, 0); + } + + #[test] + fn decode_header_not_terminated() { + let input = hex!("ef0001010004"); + assert_eq!(EofHeader::decode(&input), Err(EofDecodeError::MissingInput)); + } + + #[test] + fn failing_test() { + let input = hex!("ef00010100040200010006030001001404000200008000016000e0000000ef000101000402000100010400000000800000fe"); + let _ = EofHeader::decode(&input).unwrap(); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/types_section.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/types_section.md new file mode 100644 index 00000000..a4d98b2f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/eof/types_section.md @@ -0,0 +1,68 @@ +# ๐Ÿฆ€ types_section.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/bytecode/eof/types_section.rs) + +```rust +use super::{ + decode_helpers::{consume_u16, consume_u8}, + EofDecodeError, +}; +use std::vec::Vec; + +/// Types section that contains stack information for matching code section. +#[derive(Debug, Clone, Default, Hash, PartialEq, Eq, Copy)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TypesSection { + /// inputs - 1 byte - `0x00-0x7F` + /// number of stack elements the code section consumes + pub inputs: u8, + /// outputs - 1 byte - `0x00-0x80` + /// number of stack elements the code section returns or 0x80 for non-returning functions + pub outputs: u8, + /// max_stack_height - 2 bytes - `0x0000-0x03FF` + /// maximum number of elements ever placed onto the stack by the code section + pub max_stack_size: u16, +} + +impl TypesSection { + /// Calculates the difference between the number of input and output stack elements. + #[inline] + pub const fn io_diff(&self) -> i32 { + self.outputs as i32 - self.inputs as i32 + } + + /// Encode the section into the buffer. + #[inline] + pub fn encode(&self, buffer: &mut Vec) { + buffer.push(self.inputs); + buffer.push(self.outputs); + buffer.extend_from_slice(&self.max_stack_size.to_be_bytes()); + } + + /// Decode the section from the input. + #[inline] + pub fn decode(input: &[u8]) -> Result<(Self, &[u8]), EofDecodeError> { + let (input, inputs) = consume_u8(input)?; + let (input, outputs) = consume_u8(input)?; + let (input, max_stack_size) = consume_u16(input)?; + let section = Self { + inputs, + outputs, + max_stack_size, + }; + section.validate()?; + Ok((section, input)) + } + + /// Validate the section. + pub fn validate(&self) -> Result<(), EofDecodeError> { + if self.inputs > 0x7f || self.outputs > 0x80 || self.max_stack_size > 0x03FF { + return Err(EofDecodeError::InvalidTypesSection); + } + if self.inputs as u16 > self.max_stack_size { + return Err(EofDecodeError::InvalidTypesSection); + } + Ok(()) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/legacy.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/legacy.md new file mode 100644 index 00000000..3e4633e0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/legacy.md @@ -0,0 +1,74 @@ +# ๐Ÿฆ€ legacy.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/bytecode/legacy.rs) + +```rust +mod jump_map; + +pub use jump_map::JumpTable; + +use crate::Bytes; +use bitvec::{bitvec, order::Lsb0}; +use std::sync::Arc; + +/// Legacy analyzed +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct LegacyAnalyzedBytecode { + /// Bytecode with 32 zero bytes padding. + bytecode: Bytes, + /// Original bytes length. + original_len: usize, + /// Jump table. + jump_table: JumpTable, +} + +impl Default for LegacyAnalyzedBytecode { + #[inline] + fn default() -> Self { + Self { + bytecode: Bytes::from_static(&[0]), + original_len: 0, + jump_table: JumpTable(Arc::new(bitvec![u8, Lsb0; 0])), + } + } +} + +impl LegacyAnalyzedBytecode { + /// Create new analyzed bytecode. + pub fn new(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self { + Self { + bytecode, + original_len, + jump_table, + } + } + + /// Returns a reference to the bytecode. + /// + /// The bytecode is padded with 32 zero bytes. + pub fn bytecode(&self) -> &Bytes { + &self.bytecode + } + + /// Original bytes length. + pub fn original_len(&self) -> usize { + self.original_len + } + + /// Original bytes without padding. + pub fn original_bytes(&self) -> Bytes { + self.bytecode.slice(..self.original_len) + } + + /// Original bytes without padding. + pub fn original_byte_slice(&self) -> &[u8] { + &self.bytecode[..self.original_len] + } + + /// Jumptable of analyzed bytes. + pub fn jump_table(&self) -> &JumpTable { + &self.jump_table + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/legacy/jump_map.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/legacy/jump_map.md new file mode 100644 index 00000000..62d6e877 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/bytecode/legacy/jump_map.md @@ -0,0 +1,42 @@ +# ๐Ÿฆ€ jump_map.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/bytecode/legacy/jump_map.rs) + +```rust +use crate::hex; +use bitvec::vec::BitVec; +use std::{fmt::Debug, sync::Arc}; + +/// A map of valid `jump` destinations. +#[derive(Clone, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct JumpTable(pub Arc>); + +impl Debug for JumpTable { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("JumpTable") + .field("map", &hex::encode(self.0.as_raw_slice())) + .finish() + } +} + +impl JumpTable { + /// Get the raw bytes of the jump map + #[inline] + pub fn as_slice(&self) -> &[u8] { + self.0.as_raw_slice() + } + + /// Construct a jump map from raw bytes + #[inline] + pub fn from_slice(slice: &[u8]) -> Self { + Self(Arc::new(BitVec::from_slice(slice))) + } + + /// Check if `pc` is a valid jump destination. + #[inline] + pub fn is_valid(&self, pc: usize) -> bool { + pc < self.0.len() && self.0[pc] + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/constants.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/constants.md new file mode 100644 index 00000000..a65589a2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/constants.md @@ -0,0 +1,68 @@ +# ๐Ÿฆ€ constants.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/constants.rs) + +```rust +use alloy_primitives::{address, Address}; + +/// EIP-170: Contract code size limit +/// +/// By default the limit is `0x6000` (~25kb) +pub const MAX_CODE_SIZE: usize = 0x6000; + +/// Number of block hashes that EVM can access in the past (pre-Prague). +pub const BLOCK_HASH_HISTORY: usize = 256; + +/// EIP-2935: Serve historical block hashes from state +/// +/// Number of block hashes the EVM can access in the past (Prague). +/// +/// # Note +/// +/// This is named `HISTORY_SERVE_WINDOW` in the EIP. +pub const BLOCKHASH_SERVE_WINDOW: usize = 8192; + +/// EIP-2935: Serve historical block hashes from state +/// +/// The address where historical blockhashes are available. +/// +/// # Note +/// +/// This is named `HISTORY_STORAGE_ADDRESS` in the EIP. +pub const BLOCKHASH_STORAGE_ADDRESS: Address = address!("25a219378dad9b3503c8268c9ca836a52427a4fb"); + +/// EIP-3860: Limit and meter initcode +/// +/// Limit of maximum initcode size is `2 * MAX_CODE_SIZE`. +pub const MAX_INITCODE_SIZE: usize = 2 * MAX_CODE_SIZE; + +/// The address of precompile 3, which is handled specially in a few places. +pub const PRECOMPILE3: Address = + Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]); + +// === EIP-4844 constants === + +/// Gas consumption of a single data blob (== blob byte size). +pub const GAS_PER_BLOB: u64 = 1 << 17; + +/// Target number of the blob per block. +pub const TARGET_BLOB_NUMBER_PER_BLOCK: u64 = 3; + +/// Max number of blobs per block +pub const MAX_BLOB_NUMBER_PER_BLOCK: u64 = 2 * TARGET_BLOB_NUMBER_PER_BLOCK; + +/// Maximum consumable blob gas for data blobs per block. +pub const MAX_BLOB_GAS_PER_BLOCK: u64 = MAX_BLOB_NUMBER_PER_BLOCK * GAS_PER_BLOB; + +/// Target consumable blob gas for data blobs per block (for 1559-like pricing). +pub const TARGET_BLOB_GAS_PER_BLOCK: u64 = TARGET_BLOB_NUMBER_PER_BLOCK * GAS_PER_BLOB; + +/// Minimum gas price for data blobs. +pub const MIN_BLOB_GASPRICE: u64 = 1; + +/// Controls the maximum rate of change for blob gas price. +pub const BLOB_GASPRICE_UPDATE_FRACTION: u64 = 3338477; + +/// First version of the blob. +pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/db.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/db.md new file mode 100644 index 00000000..24429878 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/db.md @@ -0,0 +1,151 @@ +# ๐Ÿฆ€ db.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/db.rs) + +```rust +use crate::{Account, AccountInfo, Address, Bytecode, HashMap, B256, U256}; +use auto_impl::auto_impl; + +pub mod components; +pub use components::{ + BlockHash, BlockHashRef, DatabaseComponentError, DatabaseComponents, State, StateRef, +}; + +/// EVM database interface. +#[auto_impl(&mut, Box)] +pub trait Database { + /// The database error type. + type Error; + + /// Get basic account information. + fn basic(&mut self, address: Address) -> Result, Self::Error>; + + /// Get account code by its hash. + fn code_by_hash(&mut self, code_hash: B256) -> Result; + + /// Get storage value of address at index. + fn storage(&mut self, address: Address, index: U256) -> Result; + + /// Get block hash by block number. + fn block_hash(&mut self, number: U256) -> Result; +} + +/// EVM database commit interface. +#[auto_impl(&mut, Box)] +pub trait DatabaseCommit { + /// Commit changes to the database. + fn commit(&mut self, changes: HashMap); +} + +/// EVM database interface. +/// +/// Contains the same methods as [`Database`], but with `&self` receivers instead of `&mut self`. +/// +/// Use [`WrapDatabaseRef`] to provide [`Database`] implementation for a type +/// that only implements this trait. +#[auto_impl(&, &mut, Box, Rc, Arc)] +pub trait DatabaseRef { + /// The database error type. + type Error; + + /// Get basic account information. + fn basic_ref(&self, address: Address) -> Result, Self::Error>; + + /// Get account code by its hash. + fn code_by_hash_ref(&self, code_hash: B256) -> Result; + + /// Get storage value of address at index. + fn storage_ref(&self, address: Address, index: U256) -> Result; + + /// Get block hash by block number. + fn block_hash_ref(&self, number: U256) -> Result; +} + +/// Wraps a [`DatabaseRef`] to provide a [`Database`] implementation. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WrapDatabaseRef(pub T); + +impl From for WrapDatabaseRef { + #[inline] + fn from(f: F) -> Self { + WrapDatabaseRef(f) + } +} + +pub trait DatabaseWithDebugError: Database +where + ::Error: std::fmt::Debug + std::fmt::Display, +{ +} + +impl Database for WrapDatabaseRef { + type Error = T::Error; + + #[inline] + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.0.basic_ref(address) + } + + #[inline] + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.0.code_by_hash_ref(code_hash) + } + + #[inline] + fn storage(&mut self, address: Address, index: U256) -> Result { + self.0.storage_ref(address, index) + } + + #[inline] + fn block_hash(&mut self, number: U256) -> Result { + self.0.block_hash_ref(number) + } +} + +impl DatabaseCommit for WrapDatabaseRef { + #[inline] + fn commit(&mut self, changes: HashMap) { + self.0.commit(changes) + } +} + +/// Wraps a `dyn DatabaseRef` to provide a [`Database`] implementation. +#[doc(hidden)] +#[deprecated = "use `WrapDatabaseRef` instead"] +pub struct RefDBWrapper<'a, E> { + pub db: &'a dyn DatabaseRef, +} + +#[allow(deprecated)] +impl<'a, E> RefDBWrapper<'a, E> { + #[inline] + pub fn new(db: &'a dyn DatabaseRef) -> Self { + Self { db } + } +} + +#[allow(deprecated)] +impl<'a, E> Database for RefDBWrapper<'a, E> { + type Error = E; + + #[inline] + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.db.basic_ref(address) + } + + #[inline] + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.db.code_by_hash_ref(code_hash) + } + + #[inline] + fn storage(&mut self, address: Address, index: U256) -> Result { + self.db.storage_ref(address, index) + } + + #[inline] + fn block_hash(&mut self, number: U256) -> Result { + self.db.block_hash_ref(number) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/db/components.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/db/components.md new file mode 100644 index 00000000..ce7ec8fb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/db/components.md @@ -0,0 +1,89 @@ +# ๐Ÿฆ€ components.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/db/components.rs) + +```rust +//! Database that is split on State and BlockHash traits. +pub mod block_hash; +pub mod state; + +pub use block_hash::{BlockHash, BlockHashRef}; +pub use state::{State, StateRef}; + +use crate::{ + db::{Database, DatabaseRef}, + Account, AccountInfo, Address, Bytecode, HashMap, B256, U256, +}; + +use super::DatabaseCommit; + +#[derive(Debug)] +pub struct DatabaseComponents { + pub state: S, + pub block_hash: BH, +} + +#[derive(Debug)] +pub enum DatabaseComponentError { + State(SE), + BlockHash(BHE), +} + +impl Database for DatabaseComponents { + type Error = DatabaseComponentError; + + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.state.basic(address).map_err(Self::Error::State) + } + + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.state + .code_by_hash(code_hash) + .map_err(Self::Error::State) + } + + fn storage(&mut self, address: Address, index: U256) -> Result { + self.state + .storage(address, index) + .map_err(Self::Error::State) + } + + fn block_hash(&mut self, number: U256) -> Result { + self.block_hash + .block_hash(number) + .map_err(Self::Error::BlockHash) + } +} + +impl DatabaseRef for DatabaseComponents { + type Error = DatabaseComponentError; + + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + self.state.basic(address).map_err(Self::Error::State) + } + + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + self.state + .code_by_hash(code_hash) + .map_err(Self::Error::State) + } + + fn storage_ref(&self, address: Address, index: U256) -> Result { + self.state + .storage(address, index) + .map_err(Self::Error::State) + } + + fn block_hash_ref(&self, number: U256) -> Result { + self.block_hash + .block_hash(number) + .map_err(Self::Error::BlockHash) + } +} + +impl DatabaseCommit for DatabaseComponents { + fn commit(&mut self, changes: HashMap) { + self.state.commit(changes); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/db/components/block_hash.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/db/components/block_hash.md new file mode 100644 index 00000000..51a1205b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/db/components/block_hash.md @@ -0,0 +1,51 @@ +# ๐Ÿฆ€ block_hash.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/db/components/block_hash.rs) + +```rust +//! BlockHash database component from [`crate::db::Database`] +//! it is used inside [`crate::db::DatabaseComponents`] + +use crate::{B256, U256}; +use auto_impl::auto_impl; +use core::ops::Deref; +use std::sync::Arc; + +#[auto_impl(&mut, Box)] +pub trait BlockHash { + type Error; + + /// Get block hash by block number + fn block_hash(&mut self, number: U256) -> Result; +} + +#[auto_impl(&, &mut, Box, Rc, Arc)] +pub trait BlockHashRef { + type Error; + + /// Get block hash by block number + fn block_hash(&self, number: U256) -> Result; +} + +impl BlockHash for &T +where + T: BlockHashRef, +{ + type Error = ::Error; + + fn block_hash(&mut self, number: U256) -> Result { + BlockHashRef::block_hash(*self, number) + } +} + +impl BlockHash for Arc +where + T: BlockHashRef, +{ + type Error = ::Error; + + fn block_hash(&mut self, number: U256) -> Result { + self.deref().block_hash(number) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/db/components/state.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/db/components/state.md new file mode 100644 index 00000000..ecedd20a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/db/components/state.md @@ -0,0 +1,79 @@ +# ๐Ÿฆ€ state.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/db/components/state.rs) + +```rust +//! State database component from [`crate::db::Database`] +//! it is used inside [`crate::db::DatabaseComponents`] + +use crate::{AccountInfo, Address, Bytecode, B256, U256}; +use auto_impl::auto_impl; +use core::ops::Deref; +use std::sync::Arc; + +#[auto_impl(&mut, Box)] +pub trait State { + type Error; + + /// Get basic account information. + fn basic(&mut self, address: Address) -> Result, Self::Error>; + + /// Get account code by its hash + fn code_by_hash(&mut self, code_hash: B256) -> Result; + + /// Get storage value of address at index. + fn storage(&mut self, address: Address, index: U256) -> Result; +} + +#[auto_impl(&, &mut, Box, Rc, Arc)] +pub trait StateRef { + type Error; + + /// Get basic account information. + fn basic(&self, address: Address) -> Result, Self::Error>; + + /// Get account code by its hash + fn code_by_hash(&self, code_hash: B256) -> Result; + + /// Get storage value of address at index. + fn storage(&self, address: Address, index: U256) -> Result; +} + +impl State for &T +where + T: StateRef, +{ + type Error = ::Error; + + fn basic(&mut self, address: Address) -> Result, Self::Error> { + StateRef::basic(*self, address) + } + + fn code_by_hash(&mut self, code_hash: B256) -> Result { + StateRef::code_by_hash(*self, code_hash) + } + + fn storage(&mut self, address: Address, index: U256) -> Result { + StateRef::storage(*self, address, index) + } +} + +impl State for Arc +where + T: StateRef, +{ + type Error = ::Error; + + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.deref().basic(address) + } + + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.deref().code_by_hash(code_hash) + } + + fn storage(&mut self, address: Address, index: U256) -> Result { + self.deref().storage(address, index) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/env.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/env.md new file mode 100644 index 00000000..bf6a55f1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/env.md @@ -0,0 +1,797 @@ +# ๐Ÿฆ€ env.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/env.rs) + +```rust +pub mod handler_cfg; + +pub use handler_cfg::{CfgEnvWithHandlerCfg, EnvWithHandlerCfg, HandlerCfg}; + +use crate::{ + calc_blob_gasprice, Account, Address, Bytes, HashMap, InvalidHeader, InvalidTransaction, Spec, + SpecId, B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, U256, + VERSIONED_HASH_VERSION_KZG, +}; +use core::cmp::{min, Ordering}; +use core::hash::Hash; +use std::boxed::Box; +use std::vec::Vec; + +/// EVM environment configuration. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Env { + /// Configuration of the EVM itself. + pub cfg: CfgEnv, + /// Configuration of the block the transaction is in. + pub block: BlockEnv, + /// Configuration of the transaction that is being executed. + pub tx: TxEnv, +} + +impl Env { + /// Resets environment to default values. + #[inline] + pub fn clear(&mut self) { + *self = Self::default(); + } + + /// Create boxed [Env]. + #[inline] + pub fn boxed(cfg: CfgEnv, block: BlockEnv, tx: TxEnv) -> Box { + Box::new(Self { cfg, block, tx }) + } + + /// Calculates the effective gas price of the transaction. + #[inline] + pub fn effective_gas_price(&self) -> U256 { + if let Some(priority_fee) = self.tx.gas_priority_fee { + min(self.tx.gas_price, self.block.basefee + priority_fee) + } else { + self.tx.gas_price + } + } + + /// Calculates the [EIP-4844] `data_fee` of the transaction. + /// + /// Returns `None` if `Cancun` is not enabled. This is enforced in [`Env::validate_block_env`]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + #[inline] + pub fn calc_data_fee(&self) -> Option { + self.block.get_blob_gasprice().map(|blob_gas_price| { + U256::from(blob_gas_price).saturating_mul(U256::from(self.tx.get_total_blob_gas())) + }) + } + + /// Calculates the maximum [EIP-4844] `data_fee` of the transaction. + /// + /// This is used for ensuring that the user has at least enough funds to pay the + /// `max_fee_per_blob_gas * total_blob_gas`, on top of regular gas costs. + /// + /// See EIP-4844: + /// + pub fn calc_max_data_fee(&self) -> Option { + self.tx.max_fee_per_blob_gas.map(|max_fee_per_blob_gas| { + max_fee_per_blob_gas.saturating_mul(U256::from(self.tx.get_total_blob_gas())) + }) + } + + /// Validate the block environment. + #[inline] + pub fn validate_block_env(&self) -> Result<(), InvalidHeader> { + // `prevrandao` is required for the merge + if SPEC::enabled(SpecId::MERGE) && self.block.prevrandao.is_none() { + return Err(InvalidHeader::PrevrandaoNotSet); + } + // `excess_blob_gas` is required for Cancun + if SPEC::enabled(SpecId::CANCUN) && self.block.blob_excess_gas_and_price.is_none() { + return Err(InvalidHeader::ExcessBlobGasNotSet); + } + Ok(()) + } + + /// Validate transaction data that is set inside ENV and return error if something is wrong. + /// + /// Return initial spend gas (Gas needed to execute transaction). + #[inline] + pub fn validate_tx(&self) -> Result<(), InvalidTransaction> { + // BASEFEE tx check + if SPEC::enabled(SpecId::LONDON) { + if let Some(priority_fee) = self.tx.gas_priority_fee { + if priority_fee > self.tx.gas_price { + // or gas_max_fee for eip1559 + return Err(InvalidTransaction::PriorityFeeGreaterThanMaxFee); + } + } + + // check minimal cost against basefee + if !self.cfg.is_base_fee_check_disabled() + && self.effective_gas_price() < self.block.basefee + { + return Err(InvalidTransaction::GasPriceLessThanBasefee); + } + } + + // Check if gas_limit is more than block_gas_limit + if !self.cfg.is_block_gas_limit_disabled() + && U256::from(self.tx.gas_limit) > self.block.gas_limit + { + return Err(InvalidTransaction::CallerGasLimitMoreThanBlock); + } + + // EIP-3860: Limit and meter initcode + if SPEC::enabled(SpecId::SHANGHAI) && self.tx.transact_to.is_create() { + let max_initcode_size = self + .cfg + .limit_contract_code_size + .map(|limit| limit.saturating_mul(2)) + .unwrap_or(MAX_INITCODE_SIZE); + if self.tx.data.len() > max_initcode_size { + return Err(InvalidTransaction::CreateInitCodeSizeLimit); + } + } + + // Check if the transaction's chain id is correct + if let Some(tx_chain_id) = self.tx.chain_id { + if tx_chain_id != self.cfg.chain_id { + return Err(InvalidTransaction::InvalidChainId); + } + } + + // Check that access list is empty for transactions before BERLIN + if !SPEC::enabled(SpecId::BERLIN) && !self.tx.access_list.is_empty() { + return Err(InvalidTransaction::AccessListNotSupported); + } + + // - For CANCUN and later, check that the gas price is not more than the tx max + // - For before CANCUN, check that `blob_hashes` and `max_fee_per_blob_gas` are empty / not set + if SPEC::enabled(SpecId::CANCUN) { + // Presence of max_fee_per_blob_gas means that this is blob transaction. + if let Some(max) = self.tx.max_fee_per_blob_gas { + // ensure that the user was willing to at least pay the current blob gasprice + let price = self.block.get_blob_gasprice().expect("already checked"); + if U256::from(price) > max { + return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); + } + + // there must be at least one blob + if self.tx.blob_hashes.is_empty() { + return Err(InvalidTransaction::EmptyBlobs); + } + + // The field `to` deviates slightly from the semantics with the exception + // that it MUST NOT be nil and therefore must always represent + // a 20-byte address. This means that blob transactions cannot + // have the form of a create transaction. + if self.tx.transact_to.is_create() { + return Err(InvalidTransaction::BlobCreateTransaction); + } + + // all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG + for blob in self.tx.blob_hashes.iter() { + if blob[0] != VERSIONED_HASH_VERSION_KZG { + return Err(InvalidTransaction::BlobVersionNotSupported); + } + } + + // ensure the total blob gas spent is at most equal to the limit + // assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK + if self.tx.blob_hashes.len() > MAX_BLOB_NUMBER_PER_BLOCK as usize { + return Err(InvalidTransaction::TooManyBlobs); + } + } + } else { + if !self.tx.blob_hashes.is_empty() { + return Err(InvalidTransaction::BlobVersionedHashesNotSupported); + } + if self.tx.max_fee_per_blob_gas.is_some() { + return Err(InvalidTransaction::MaxFeePerBlobGasNotSupported); + } + } + + if SPEC::enabled(SpecId::PRAGUE) { + if !self.tx.eof_initcodes.is_empty() { + // If initcode is set other fields must be empty + if !self.tx.blob_hashes.is_empty() { + return Err(InvalidTransaction::BlobVersionedHashesNotSupported); + } + // EOF Create tx extends EIP-1559 tx. It must have max_fee_per_blob_gas + if self.tx.max_fee_per_blob_gas.is_some() { + return Err(InvalidTransaction::MaxFeePerBlobGasNotSupported); + } + // EOF Create must have a to address + if matches!(self.tx.transact_to, TransactTo::Call(_)) { + return Err(InvalidTransaction::EofCrateShouldHaveToAddress); + } + } else { + // If initcode is set check its bounds. + if self.tx.eof_initcodes.len() > 256 { + return Err(InvalidTransaction::EofInitcodesNumberLimit); + } + if self + .tx + .eof_initcodes_hashed + .iter() + .any(|(_, i)| i.len() >= MAX_INITCODE_SIZE) + { + return Err(InvalidTransaction::EofInitcodesSizeLimit); + } + } + } else { + // Initcode set when not supported. + if !self.tx.eof_initcodes.is_empty() { + return Err(InvalidTransaction::EofInitcodesNotSupported); + } + } + + Ok(()) + } + + /// Validate transaction against state. + #[inline] + pub fn validate_tx_against_state( + &self, + account: &mut Account, + ) -> Result<(), InvalidTransaction> { + // EIP-3607: Reject transactions from senders with deployed code + // This EIP is introduced after london but there was no collision in past + // so we can leave it enabled always + if !self.cfg.is_eip3607_disabled() && account.info.code_hash != KECCAK_EMPTY { + return Err(InvalidTransaction::RejectCallerWithCode); + } + + // Check that the transaction's nonce is correct + if let Some(tx) = self.tx.nonce { + let state = account.info.nonce; + match tx.cmp(&state) { + Ordering::Greater => { + return Err(InvalidTransaction::NonceTooHigh { tx, state }); + } + Ordering::Less => { + return Err(InvalidTransaction::NonceTooLow { tx, state }); + } + _ => {} + } + } + + let mut balance_check = U256::from(self.tx.gas_limit) + .checked_mul(self.tx.gas_price) + .and_then(|gas_cost| gas_cost.checked_add(self.tx.value)) + .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; + + if SPEC::enabled(SpecId::CANCUN) { + // if the tx is not a blob tx, this will be None, so we add zero + let data_fee = self.calc_max_data_fee().unwrap_or_default(); + balance_check = balance_check + .checked_add(U256::from(data_fee)) + .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; + } + + // Check if account has enough balance for gas_limit*gas_price and value transfer. + // Transfer will be done inside `*_inner` functions. + if balance_check > account.info.balance { + if self.cfg.is_balance_check_disabled() { + // Add transaction cost to balance to ensure execution doesn't fail. + account.info.balance = balance_check; + } else { + return Err(InvalidTransaction::LackOfFundForMaxFee { + fee: Box::new(balance_check), + balance: Box::new(account.info.balance), + }); + } + } + + Ok(()) + } +} + +/// EVM configuration. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub struct CfgEnv { + /// Chain ID of the EVM, it will be compared to the transaction's Chain ID. + /// Chain ID is introduced EIP-155 + pub chain_id: u64, + /// KZG Settings for point evaluation precompile. By default, this is loaded from the ethereum mainnet trusted setup. + #[cfg(feature = "c-kzg")] + #[cfg_attr(feature = "serde", serde(skip))] + pub kzg_settings: crate::kzg::EnvKzgSettings, + /// Bytecode that is created with CREATE/CREATE2 is by default analysed and jumptable is created. + /// This is very beneficial for testing and speeds up execution of that bytecode if called multiple times. + /// + /// Default: Analyse + pub perf_analyse_created_bytecodes: AnalysisKind, + /// If some it will effects EIP-170: Contract code size limit. Useful to increase this because of tests. + /// By default it is 0x6000 (~25kb). + pub limit_contract_code_size: Option, + /// A hard memory limit in bytes beyond which [crate::result::OutOfGasError::Memory] cannot be resized. + /// + /// In cases where the gas limit may be extraordinarily high, it is recommended to set this to + /// a sane value to prevent memory allocation panics. Defaults to `2^32 - 1` bytes per + /// EIP-1985. + #[cfg(feature = "memory_limit")] + pub memory_limit: u64, + /// Skip balance checks if true. Adds transaction cost to balance to ensure execution doesn't fail. + #[cfg(feature = "optional_balance_check")] + pub disable_balance_check: bool, + /// There are use cases where it's allowed to provide a gas limit that's higher than a block's gas limit. To that + /// end, you can disable the block gas limit validation. + /// By default, it is set to `false`. + #[cfg(feature = "optional_block_gas_limit")] + pub disable_block_gas_limit: bool, + /// EIP-3607 rejects transactions from senders with deployed code. In development, it can be desirable to simulate + /// calls from contracts, which this setting allows. + /// By default, it is set to `false`. + #[cfg(feature = "optional_eip3607")] + pub disable_eip3607: bool, + /// Disables all gas refunds. This is useful when using chains that have gas refunds disabled e.g. Avalanche. + /// Reasoning behind removing gas refunds can be found in EIP-3298. + /// By default, it is set to `false`. + #[cfg(feature = "optional_gas_refund")] + pub disable_gas_refund: bool, + /// Disables base fee checks for EIP-1559 transactions. + /// This is useful for testing method calls with zero gas price. + /// By default, it is set to `false`. + #[cfg(feature = "optional_no_base_fee")] + pub disable_base_fee: bool, + /// Disables the payout of the reward to the beneficiary. + /// By default, it is set to `false`. + #[cfg(feature = "optional_beneficiary_reward")] + pub disable_beneficiary_reward: bool, +} + +impl CfgEnv { + pub fn with_chain_id(mut self, chain_id: u64) -> Self { + self.chain_id = chain_id; + self + } + + #[cfg(feature = "optional_eip3607")] + pub fn is_eip3607_disabled(&self) -> bool { + self.disable_eip3607 + } + + #[cfg(not(feature = "optional_eip3607"))] + pub fn is_eip3607_disabled(&self) -> bool { + false + } + + #[cfg(feature = "optional_balance_check")] + pub fn is_balance_check_disabled(&self) -> bool { + self.disable_balance_check + } + + #[cfg(not(feature = "optional_balance_check"))] + pub fn is_balance_check_disabled(&self) -> bool { + false + } + + #[cfg(feature = "optional_gas_refund")] + pub fn is_gas_refund_disabled(&self) -> bool { + self.disable_gas_refund + } + + #[cfg(not(feature = "optional_gas_refund"))] + pub fn is_gas_refund_disabled(&self) -> bool { + false + } + + #[cfg(feature = "optional_no_base_fee")] + pub fn is_base_fee_check_disabled(&self) -> bool { + self.disable_base_fee + } + + #[cfg(not(feature = "optional_no_base_fee"))] + pub fn is_base_fee_check_disabled(&self) -> bool { + false + } + + #[cfg(feature = "optional_block_gas_limit")] + pub fn is_block_gas_limit_disabled(&self) -> bool { + self.disable_block_gas_limit + } + + #[cfg(not(feature = "optional_block_gas_limit"))] + pub fn is_block_gas_limit_disabled(&self) -> bool { + false + } + + #[cfg(feature = "optional_beneficiary_reward")] + pub fn is_beneficiary_reward_disabled(&self) -> bool { + self.disable_beneficiary_reward + } + + #[cfg(not(feature = "optional_beneficiary_reward"))] + pub fn is_beneficiary_reward_disabled(&self) -> bool { + false + } +} + +impl Default for CfgEnv { + fn default() -> Self { + Self { + chain_id: 1, + perf_analyse_created_bytecodes: AnalysisKind::default(), + limit_contract_code_size: None, + #[cfg(feature = "c-kzg")] + kzg_settings: crate::kzg::EnvKzgSettings::Default, + #[cfg(feature = "memory_limit")] + memory_limit: (1 << 32) - 1, + #[cfg(feature = "optional_balance_check")] + disable_balance_check: false, + #[cfg(feature = "optional_block_gas_limit")] + disable_block_gas_limit: false, + #[cfg(feature = "optional_eip3607")] + disable_eip3607: false, + #[cfg(feature = "optional_gas_refund")] + disable_gas_refund: false, + #[cfg(feature = "optional_no_base_fee")] + disable_base_fee: false, + #[cfg(feature = "optional_beneficiary_reward")] + disable_beneficiary_reward: false, + } + } +} + +/// The block environment. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct BlockEnv { + /// The number of ancestor blocks of this block (block height). + pub number: U256, + /// Coinbase or miner or address that created and signed the block. + /// + /// This is the receiver address of all the gas spent in the block. + pub coinbase: Address, + + /// The timestamp of the block in seconds since the UNIX epoch. + pub timestamp: U256, + /// The gas limit of the block. + pub gas_limit: U256, + /// The base fee per gas, added in the London upgrade with [EIP-1559]. + /// + /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 + pub basefee: U256, + /// The difficulty of the block. + /// + /// Unused after the Paris (AKA the merge) upgrade, and replaced by `prevrandao`. + pub difficulty: U256, + /// The output of the randomness beacon provided by the beacon chain. + /// + /// Replaces `difficulty` after the Paris (AKA the merge) upgrade with [EIP-4399]. + /// + /// NOTE: `prevrandao` can be found in a block in place of `mix_hash`. + /// + /// [EIP-4399]: https://eips.ethereum.org/EIPS/eip-4399 + pub prevrandao: Option, + /// Excess blob gas and blob gasprice. + /// See also [`crate::calc_excess_blob_gas`] + /// and [`calc_blob_gasprice`]. + /// + /// Incorporated as part of the Cancun upgrade via [EIP-4844]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + pub blob_excess_gas_and_price: Option, +} + +impl BlockEnv { + /// Takes `blob_excess_gas` saves it inside env + /// and calculates `blob_fee` with [`BlobExcessGasAndPrice`]. + pub fn set_blob_excess_gas_and_price(&mut self, excess_blob_gas: u64) { + self.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new(excess_blob_gas)); + } + /// See [EIP-4844] and [`crate::calc_blob_gasprice`]. + /// + /// Returns `None` if `Cancun` is not enabled. This is enforced in [`Env::validate_block_env`]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + #[inline] + pub fn get_blob_gasprice(&self) -> Option { + self.blob_excess_gas_and_price + .as_ref() + .map(|a| a.blob_gasprice) + } + + /// Return `blob_excess_gas` header field. See [EIP-4844]. + /// + /// Returns `None` if `Cancun` is not enabled. This is enforced in [`Env::validate_block_env`]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + #[inline] + pub fn get_blob_excess_gas(&self) -> Option { + self.blob_excess_gas_and_price + .as_ref() + .map(|a| a.excess_blob_gas) + } + + /// Clears environment and resets fields to default values. + #[inline] + pub fn clear(&mut self) { + *self = Self::default(); + } +} + +impl Default for BlockEnv { + fn default() -> Self { + Self { + number: U256::ZERO, + coinbase: Address::ZERO, + timestamp: U256::from(1), + gas_limit: U256::MAX, + basefee: U256::ZERO, + difficulty: U256::ZERO, + prevrandao: Some(B256::ZERO), + blob_excess_gas_and_price: Some(BlobExcessGasAndPrice::new(0)), + } + } +} + +/// The transaction environment. +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TxEnv { + /// Caller aka Author aka transaction signer. + pub caller: Address, + /// The gas limit of the transaction. + pub gas_limit: u64, + /// The gas price of the transaction. + pub gas_price: U256, + /// The destination of the transaction. + pub transact_to: TransactTo, + /// The value sent to `transact_to`. + pub value: U256, + /// The data of the transaction. + pub data: Bytes, + /// The nonce of the transaction. + /// + /// Caution: If set to `None`, then nonce validation against the account's nonce is skipped: [InvalidTransaction::NonceTooHigh] and [InvalidTransaction::NonceTooLow] + pub nonce: Option, + + /// The chain ID of the transaction. If set to `None`, no checks are performed. + /// + /// Incorporated as part of the Spurious Dragon upgrade via [EIP-155]. + /// + /// [EIP-155]: https://eips.ethereum.org/EIPS/eip-155 + pub chain_id: Option, + + /// A list of addresses and storage keys that the transaction plans to access. + /// + /// Added in [EIP-2930]. + /// + /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 + pub access_list: Vec<(Address, Vec)>, + + /// The priority fee per gas. + /// + /// Incorporated as part of the London upgrade via [EIP-1559]. + /// + /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 + pub gas_priority_fee: Option, + + /// The list of blob versioned hashes. Per EIP there should be at least + /// one blob present if [`Self::max_fee_per_blob_gas`] is `Some`. + /// + /// Incorporated as part of the Cancun upgrade via [EIP-4844]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + pub blob_hashes: Vec, + + /// The max fee per blob gas. + /// + /// Incorporated as part of the Cancun upgrade via [EIP-4844]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + pub max_fee_per_blob_gas: Option, + + /// EOF Initcodes for EOF CREATE transaction + /// + /// Incorporated as part of the Prague upgrade via [EOF] + /// + /// [EOF]: https://eips.ethereum.org/EIPS/eip-4844 + pub eof_initcodes: Vec, + + /// Internal Temporary field that stores the hashes of the EOF initcodes. + /// + /// Those are always cleared after the transaction is executed. + /// And calculated/overwritten every time transaction starts. + /// They are calculated from the [`Self::eof_initcodes`] field. + pub eof_initcodes_hashed: HashMap, + + #[cfg_attr(feature = "serde", serde(flatten))] + #[cfg(feature = "optimism")] + /// Optimism fields. + pub optimism: OptimismFields, +} + +pub enum TxType { + Legacy, + Eip1559, + BlobTx, + EofCreate, +} + +impl TxEnv { + /// See [EIP-4844], [`Env::calc_data_fee`], and [`Env::calc_max_data_fee`]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + #[inline] + pub fn get_total_blob_gas(&self) -> u64 { + GAS_PER_BLOB * self.blob_hashes.len() as u64 + } + + /// Clears environment and resets fields to default values. + #[inline] + pub fn clear(&mut self) { + *self = Self::default(); + } +} + +impl Default for TxEnv { + fn default() -> Self { + Self { + caller: Address::ZERO, + gas_limit: u64::MAX, + gas_price: U256::ZERO, + gas_priority_fee: None, + transact_to: TransactTo::Call(Address::ZERO), // will do nothing + value: U256::ZERO, + data: Bytes::new(), + chain_id: None, + nonce: None, + access_list: Vec::new(), + blob_hashes: Vec::new(), + max_fee_per_blob_gas: None, + eof_initcodes: Vec::new(), + eof_initcodes_hashed: HashMap::new(), + #[cfg(feature = "optimism")] + optimism: OptimismFields::default(), + } + } +} + +/// Structure holding block blob excess gas and it calculates blob fee. +/// +/// Incorporated as part of the Cancun upgrade via [EIP-4844]. +/// +/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct BlobExcessGasAndPrice { + /// The excess blob gas of the block. + pub excess_blob_gas: u64, + /// The calculated blob gas price based on the `excess_blob_gas`, See [calc_blob_gasprice] + pub blob_gasprice: u128, +} + +impl BlobExcessGasAndPrice { + /// Creates a new instance by calculating the blob gas price with [`calc_blob_gasprice`]. + pub fn new(excess_blob_gas: u64) -> Self { + let blob_gasprice = calc_blob_gasprice(excess_blob_gas); + Self { + excess_blob_gas, + blob_gasprice, + } + } +} + +/// Additional [TxEnv] fields for optimism. +#[cfg(feature = "optimism")] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct OptimismFields { + /// The source hash is used to make sure that deposit transactions do + /// not have identical hashes. + /// + /// L1 originated deposit transaction source hashes are computed using + /// the hash of the l1 block hash and the l1 log index. + /// L1 attributes deposit source hashes are computed with the l1 block + /// hash and the sequence number = l2 block number - l2 epoch start + /// block number. + /// + /// These two deposit transaction sources specify a domain in the outer + /// hash so there are no collisions. + pub source_hash: Option, + /// The amount to increase the balance of the `from` account as part of + /// a deposit transaction. This is unconditional and is applied to the + /// `from` account even if the deposit transaction fails since + /// the deposit is pre-paid on L1. + pub mint: Option, + /// Whether or not the transaction is a system transaction. + pub is_system_transaction: Option, + /// An enveloped EIP-2718 typed transaction. This is used + /// to compute the L1 tx cost using the L1 block info, as + /// opposed to requiring downstream apps to compute the cost + /// externally. + /// This field is optional to allow the [TxEnv] to be constructed + /// for non-optimism chains when the `optimism` feature is enabled, + /// but the [CfgEnv] `optimism` field is set to false. + pub enveloped_tx: Option, +} + +/// Transaction destination. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum TransactTo { + /// Simple call to an address. + Call(Address), + /// Contract creation. + Create, +} + +impl TransactTo { + /// Calls the given address. + #[inline] + pub fn call(address: Address) -> Self { + Self::Call(address) + } + + /// Creates a contract. + #[inline] + pub fn create() -> Self { + Self::Create + } + /// Returns `true` if the transaction is `Call`. + #[inline] + pub fn is_call(&self) -> bool { + matches!(self, Self::Call(_)) + } + + /// Returns `true` if the transaction is `Create` or `Create2`. + #[inline] + pub fn is_create(&self) -> bool { + matches!(self, Self::Create) + } +} + +/// Create scheme. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum CreateScheme { + /// Legacy create scheme of `CREATE`. + Create, + /// Create scheme of `CREATE2`. + Create2 { + /// Salt. + salt: U256, + }, +} + +/// What bytecode analysis to perform. +#[derive(Clone, Default, Debug, Eq, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum AnalysisKind { + /// Do not perform bytecode analysis. + Raw, + /// Perform bytecode analysis. + #[default] + Analyse, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_validate_tx_chain_id() { + let mut env = Env::default(); + env.tx.chain_id = Some(1); + env.cfg.chain_id = 2; + assert_eq!( + env.validate_tx::(), + Err(InvalidTransaction::InvalidChainId) + ); + } + + #[test] + fn test_validate_tx_access_list() { + let mut env = Env::default(); + env.tx.access_list = vec![(Address::ZERO, vec![])]; + assert_eq!( + env.validate_tx::(), + Err(InvalidTransaction::AccessListNotSupported) + ); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/env/handler_cfg.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/env/handler_cfg.md new file mode 100644 index 00000000..4fd9b83d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/env/handler_cfg.md @@ -0,0 +1,165 @@ +# ๐Ÿฆ€ handler_cfg.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/env/handler_cfg.rs) + +```rust +use super::{BlockEnv, CfgEnv, Env, SpecId, TxEnv}; +use core::ops::{Deref, DerefMut}; +use std::boxed::Box; + +/// Handler configuration fields. It is used to configure the handler. +/// It contains specification id and the Optimism related field if +/// optimism feature is enabled. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub struct HandlerCfg { + /// Specification identification. + pub spec_id: SpecId, + /// Optimism related field, it will append the Optimism handle register to the EVM. + #[cfg(feature = "optimism")] + pub is_optimism: bool, +} + +impl Default for HandlerCfg { + fn default() -> Self { + Self::new(SpecId::default()) + } +} + +impl HandlerCfg { + /// Creates new `HandlerCfg` instance. + pub fn new(spec_id: SpecId) -> Self { + cfg_if::cfg_if! { + if #[cfg(all(feature = "optimism-default-handler", + not(feature = "negate-optimism-default-handler")))] { + let is_optimism = true; + } else if #[cfg(feature = "optimism")] { + let is_optimism = false; + } + } + Self { + spec_id, + #[cfg(feature = "optimism")] + is_optimism, + } + } + + /// Creates new `HandlerCfg` instance with the optimism feature. + #[cfg(feature = "optimism")] + pub fn new_with_optimism(spec_id: SpecId, is_optimism: bool) -> Self { + Self { + spec_id, + is_optimism, + } + } + + /// Returns `true` if the optimism feature is enabled and flag is set to `true`. + pub fn is_optimism(&self) -> bool { + cfg_if::cfg_if! { + if #[cfg(feature = "optimism")] { + self.is_optimism + } else { + false + } + } + } +} + +/// Configuration environment with the chain spec id. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct CfgEnvWithHandlerCfg { + /// Configuration environment. + pub cfg_env: CfgEnv, + /// Handler configuration fields. + pub handler_cfg: HandlerCfg, +} + +impl CfgEnvWithHandlerCfg { + /// Returns new instance of `CfgEnvWithHandlerCfg` with the handler configuration. + pub fn new(cfg_env: CfgEnv, handler_cfg: HandlerCfg) -> Self { + Self { + cfg_env, + handler_cfg, + } + } + + /// Returns new `CfgEnvWithHandlerCfg` instance with the chain spec id. + /// + /// is_optimism will be set to default value depending on `optimism-default-handler` feature. + pub fn new_with_spec_id(cfg_env: CfgEnv, spec_id: SpecId) -> Self { + Self::new(cfg_env, HandlerCfg::new(spec_id)) + } + + /// Enables the optimism feature. + #[cfg(feature = "optimism")] + pub fn enable_optimism(&mut self) { + self.handler_cfg.is_optimism = true; + } +} + +impl DerefMut for CfgEnvWithHandlerCfg { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.cfg_env + } +} + +impl Deref for CfgEnvWithHandlerCfg { + type Target = CfgEnv; + + fn deref(&self) -> &Self::Target { + &self.cfg_env + } +} + +/// Evm environment with the chain spec id. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct EnvWithHandlerCfg { + /// Evm enironment. + pub env: Box, + /// Handler configuration fields. + pub handler_cfg: HandlerCfg, +} + +impl EnvWithHandlerCfg { + /// Returns new `EnvWithHandlerCfg` instance. + pub fn new(env: Box, handler_cfg: HandlerCfg) -> Self { + Self { env, handler_cfg } + } + + /// Returns new `EnvWithHandlerCfg` instance with the chain spec id. + /// + /// is_optimism will be set to default value depending on `optimism-default-handler` feature. + pub fn new_with_spec_id(env: Box, spec_id: SpecId) -> Self { + Self::new(env, HandlerCfg::new(spec_id)) + } + + /// Takes `CfgEnvWithHandlerCfg` and returns new `EnvWithHandlerCfg` instance. + pub fn new_with_cfg_env(cfg: CfgEnvWithHandlerCfg, block: BlockEnv, tx: TxEnv) -> Self { + Self::new(Env::boxed(cfg.cfg_env, block, tx), cfg.handler_cfg) + } + + /// Returns the specification id. + pub const fn spec_id(&self) -> SpecId { + self.handler_cfg.spec_id + } + + /// Enables the optimism handle register. + #[cfg(feature = "optimism")] + pub fn enable_optimism(&mut self) { + self.handler_cfg.is_optimism = true; + } +} + +impl DerefMut for EnvWithHandlerCfg { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.env + } +} + +impl Deref for EnvWithHandlerCfg { + type Target = Env; + + fn deref(&self) -> &Self::Target { + &self.env + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/kzg.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/kzg.md new file mode 100644 index 00000000..4ea03a42 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/kzg.md @@ -0,0 +1,15 @@ +# ๐Ÿฆ€ kzg.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/kzg.rs) + +```rust +mod env_settings; +mod trusted_setup_points; + +pub use c_kzg::KzgSettings; +pub use env_settings::EnvKzgSettings; +pub use trusted_setup_points::{ + parse_kzg_trusted_setup, G1Points, G2Points, KzgErrors, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT, + G1_POINTS, G2_POINTS, NUM_G1_POINTS, NUM_G2_POINTS, +}; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/kzg/env_settings.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/kzg/env_settings.md new file mode 100644 index 00000000..c0c7a743 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/kzg/env_settings.md @@ -0,0 +1,65 @@ +# ๐Ÿฆ€ env_settings.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/kzg/env_settings.rs) + +```rust +use super::{ + trusted_setup_points::{G1_POINTS, G2_POINTS}, + KzgSettings, +}; +use core::hash::{Hash, Hasher}; +use once_cell::race::OnceBox; +use std::{boxed::Box, sync::Arc}; + +/// KZG Settings that allow us to specify a custom trusted setup. +/// or use hardcoded default settings. +#[derive(Debug, Clone, Default, Eq)] +pub enum EnvKzgSettings { + /// Default mainnet trusted setup + #[default] + Default, + /// Custom trusted setup. + Custom(Arc), +} + +// Implement PartialEq and Hash manually because `c_kzg::KzgSettings` does not implement them +impl PartialEq for EnvKzgSettings { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Default, Self::Default) => true, + (Self::Custom(a), Self::Custom(b)) => Arc::ptr_eq(a, b), + _ => false, + } + } +} + +impl Hash for EnvKzgSettings { + fn hash(&self, state: &mut H) { + core::mem::discriminant(self).hash(state); + match self { + Self::Default => {} + Self::Custom(settings) => Arc::as_ptr(settings).hash(state), + } + } +} + +impl EnvKzgSettings { + /// Return set KZG settings. + /// + /// In will initialize the default settings if it is not already loaded. + pub fn get(&self) -> &KzgSettings { + match self { + Self::Default => { + static DEFAULT: OnceBox = OnceBox::new(); + DEFAULT.get_or_init(|| { + let settings = + KzgSettings::load_trusted_setup(G1_POINTS.as_ref(), G2_POINTS.as_ref()) + .expect("failed to load default trusted setup"); + Box::new(settings) + }) + } + Self::Custom(settings) => settings, + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/kzg/trusted_setup_points.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/kzg/trusted_setup_points.md new file mode 100644 index 00000000..404c0a0b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/kzg/trusted_setup_points.md @@ -0,0 +1,139 @@ +# ๐Ÿฆ€ trusted_setup_points.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/kzg/trusted_setup_points.rs) + +```rust +use core::fmt; +use derive_more::{AsMut, AsRef, Deref, DerefMut}; +use std::boxed::Box; + +pub use c_kzg::{BYTES_PER_G1_POINT, BYTES_PER_G2_POINT}; + +/// Number of G1 Points. +pub const NUM_G1_POINTS: usize = 4096; + +/// Number of G2 Points. +pub const NUM_G2_POINTS: usize = 65; + +/// A newtype over list of G1 point from kzg trusted setup. +#[derive(Debug, Clone, PartialEq, AsRef, AsMut, Deref, DerefMut)] +#[repr(transparent)] +pub struct G1Points(pub [[u8; BYTES_PER_G1_POINT]; NUM_G1_POINTS]); + +impl Default for G1Points { + fn default() -> Self { + Self([[0; BYTES_PER_G1_POINT]; NUM_G1_POINTS]) + } +} + +/// A newtype over list of G2 point from kzg trusted setup. +#[derive(Debug, Clone, Eq, PartialEq, AsRef, AsMut, Deref, DerefMut)] +#[repr(transparent)] +pub struct G2Points(pub [[u8; BYTES_PER_G2_POINT]; NUM_G2_POINTS]); + +impl Default for G2Points { + fn default() -> Self { + Self([[0; BYTES_PER_G2_POINT]; NUM_G2_POINTS]) + } +} + +/// Default G1 points. +pub const G1_POINTS: &G1Points = { + const BYTES: &[u8] = include_bytes!("./g1_points.bin"); + assert!(BYTES.len() == core::mem::size_of::()); + unsafe { &*BYTES.as_ptr().cast::() } +}; + +/// Default G2 points. +pub const G2_POINTS: &G2Points = { + const BYTES: &[u8] = include_bytes!("./g2_points.bin"); + assert!(BYTES.len() == core::mem::size_of::()); + unsafe { &*BYTES.as_ptr().cast::() } +}; + +/// Parses the contents of a KZG trusted setup file into a list of G1 and G2 points. +/// +/// These can then be used to create a KZG settings object with +/// [`KzgSettings::load_trusted_setup`](c_kzg::KzgSettings::load_trusted_setup). +pub fn parse_kzg_trusted_setup( + trusted_setup: &str, +) -> Result<(Box, Box), KzgErrors> { + let mut lines = trusted_setup.lines(); + + // load number of points + let n_g1 = lines + .next() + .ok_or(KzgErrors::FileFormatError)? + .parse::() + .map_err(|_| KzgErrors::ParseError)?; + let n_g2 = lines + .next() + .ok_or(KzgErrors::FileFormatError)? + .parse::() + .map_err(|_| KzgErrors::ParseError)?; + + if n_g1 != NUM_G1_POINTS { + return Err(KzgErrors::MismatchedNumberOfPoints); + } + + if n_g2 != NUM_G2_POINTS { + return Err(KzgErrors::MismatchedNumberOfPoints); + } + + // load g1 points + let mut g1_points = Box::::default(); + for bytes in &mut g1_points.0 { + let line = lines.next().ok_or(KzgErrors::FileFormatError)?; + crate::hex::decode_to_slice(line, bytes).map_err(|_| KzgErrors::ParseError)?; + } + + // load g2 points + let mut g2_points = Box::::default(); + for bytes in &mut g2_points.0 { + let line = lines.next().ok_or(KzgErrors::FileFormatError)?; + crate::hex::decode_to_slice(line, bytes).map_err(|_| KzgErrors::ParseError)?; + } + + if lines.next().is_some() { + return Err(KzgErrors::FileFormatError); + } + + Ok((g1_points, g2_points)) +} + +#[derive(Debug)] +pub enum KzgErrors { + /// Failed to get current directory. + FailedCurrentDirectory, + /// The specified path does not exist. + PathNotExists, + /// Problems related to I/O. + IOError, + /// Not a valid file. + NotValidFile, + /// File is not properly formatted. + FileFormatError, + /// Not able to parse to usize. + ParseError, + /// Number of points does not match what is expected. + MismatchedNumberOfPoints, +} + +impl fmt::Display for KzgErrors { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::FailedCurrentDirectory => "failed to get current directory", + Self::PathNotExists => "the specified path does not exist", + Self::IOError => "IO error", + Self::NotValidFile => "not a valid file", + Self::FileFormatError => "file is not properly formatted", + Self::ParseError => "could not parse as usize", + Self::MismatchedNumberOfPoints => "number of points does not match what is expected", + }; + f.write_str(s) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for KzgErrors {} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/lib.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/lib.md new file mode 100644 index 00000000..d62d1cfd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/lib.md @@ -0,0 +1,54 @@ +# ๐Ÿฆ€ lib.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/lib.rs) + +```rust +//! # revm-primitives +//! +//! EVM primitive types. +#![warn(rustdoc::all)] +#![warn(unreachable_pub, unused_crate_dependencies)] +#![deny(unused_must_use, rust_2018_idioms)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(not(feature = "std"))] +extern crate alloc as std; + +mod bytecode; +mod constants; +pub mod db; +pub mod env; + +#[cfg(feature = "c-kzg")] +pub mod kzg; +pub mod precompile; +pub mod result; +pub mod specification; +pub mod state; +pub mod utilities; +pub use alloy_primitives::{ + self, address, b256, bytes, fixed_bytes, hex, hex_literal, ruint, uint, Address, Bytes, + FixedBytes, Log, LogData, B256, I256, U256, +}; +pub use bitvec; +pub use bytecode::*; +pub use constants::*; +pub use env::*; + +cfg_if::cfg_if! { + if #[cfg(all(not(feature = "hashbrown"), feature = "std"))] { + pub use std::collections::{hash_map, hash_set, HashMap, HashSet}; + use hashbrown as _; + } else { + pub use hashbrown::{hash_map, hash_set, HashMap, HashSet}; + } +} + +#[cfg(feature = "c-kzg")] +pub use kzg::{EnvKzgSettings, KzgSettings}; +pub use precompile::*; +pub use result::*; +pub use specification::*; +pub use state::*; +pub use utilities::*; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/precompile.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/precompile.md new file mode 100644 index 00000000..32c638d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/precompile.md @@ -0,0 +1,196 @@ +# ๐Ÿฆ€ precompile.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/precompile.rs) + +```rust +use crate::{Bytes, Env}; +use core::fmt; +use dyn_clone::DynClone; +use std::{boxed::Box, string::String, sync::Arc}; + +/// A precompile operation result. +/// +/// Returns either `Ok((gas_used, return_bytes))` or `Err(error)`. +pub type PrecompileResult = Result<(u64, Bytes), PrecompileError>; + +pub type StandardPrecompileFn = fn(&Bytes, u64) -> PrecompileResult; +pub type EnvPrecompileFn = fn(&Bytes, u64, env: &Env) -> PrecompileResult; + +/// Stateful precompile trait. It is used to create +/// a arc precompile Precompile::Stateful. +pub trait StatefulPrecompile: Sync + Send { + fn call(&self, bytes: &Bytes, gas_price: u64, env: &Env) -> PrecompileResult; +} + +/// Mutable stateful precompile trait. It is used to create +/// a boxed precompile in Precompile::StatefulMut. +pub trait StatefulPrecompileMut: DynClone + Send + Sync { + fn call_mut(&mut self, bytes: &Bytes, gas_price: u64, env: &Env) -> PrecompileResult; +} + +dyn_clone::clone_trait_object!(StatefulPrecompileMut); + +/// Arc over stateful precompile. +pub type StatefulPrecompileArc = Arc; + +/// Box over mutable stateful precompile +pub type StatefulPrecompileBox = Box; + +/// Precompile and its handlers. +#[derive(Clone)] +pub enum Precompile { + /// Standard simple precompile that takes input and gas limit. + Standard(StandardPrecompileFn), + /// Similar to Standard but takes reference to environment. + Env(EnvPrecompileFn), + /// Stateful precompile that is Arc over [`StatefulPrecompile`] trait. + /// It takes a reference to input, gas limit and environment. + Stateful(StatefulPrecompileArc), + /// Mutable stateful precompile that is Box over [`StatefulPrecompileMut`] trait. + /// It takes a reference to input, gas limit and environment. + StatefulMut(StatefulPrecompileBox), +} + +impl From for Precompile { + fn from(p: StandardPrecompileFn) -> Self { + Precompile::Standard(p) + } +} + +impl From for Precompile { + fn from(p: EnvPrecompileFn) -> Self { + Precompile::Env(p) + } +} + +impl From for Precompile { + fn from(p: StatefulPrecompileArc) -> Self { + Precompile::Stateful(p) + } +} + +impl From for Precompile { + fn from(p: StatefulPrecompileBox) -> Self { + Precompile::StatefulMut(p) + } +} + +impl fmt::Debug for Precompile { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Precompile::Standard(_) => f.write_str("Standard"), + Precompile::Env(_) => f.write_str("Env"), + Precompile::Stateful(_) => f.write_str("Stateful"), + Precompile::StatefulMut(_) => f.write_str("StatefulMut"), + } + } +} + +impl Precompile { + /// Create a new stateful precompile. + pub fn new_stateful(p: P) -> Self { + Self::Stateful(Arc::new(p)) + } + + /// Create a new mutable stateful precompile. + pub fn new_stateful_mut(p: P) -> Self { + Self::StatefulMut(Box::new(p)) + } + + /// Call the precompile with the given input and gas limit and return the result. + pub fn call(&mut self, bytes: &Bytes, gas_price: u64, env: &Env) -> PrecompileResult { + match self { + Precompile::Standard(p) => p(bytes, gas_price), + Precompile::Env(p) => p(bytes, gas_price, env), + Precompile::Stateful(p) => p.call(bytes, gas_price, env), + Precompile::StatefulMut(p) => p.call_mut(bytes, gas_price, env), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum PrecompileError { + /// out of gas is the main error. Others are here just for completeness + OutOfGas, + // Blake2 errors + Blake2WrongLength, + Blake2WrongFinalIndicatorFlag, + // Modexp errors + ModexpExpOverflow, + ModexpBaseOverflow, + ModexpModOverflow, + // Bn128 errors + Bn128FieldPointNotAMember, + Bn128AffineGFailedToCreate, + Bn128PairLength, + // Blob errors + /// The input length is not exactly 192 bytes. + BlobInvalidInputLength, + /// The commitment does not match the versioned hash. + BlobMismatchedVersion, + /// The proof verification failed. + BlobVerifyKzgProofFailed, + /// Catch-all variant for other errors. + Other(String), +} + +impl PrecompileError { + pub fn other(err: impl Into) -> Self { + Self::Other(err.into()) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for PrecompileError {} + +impl fmt::Display for PrecompileError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::OutOfGas => "out of gas", + Self::Blake2WrongLength => "wrong input length for blake2", + Self::Blake2WrongFinalIndicatorFlag => "wrong final indicator flag for blake2", + Self::ModexpExpOverflow => "modexp exp overflow", + Self::ModexpBaseOverflow => "modexp base overflow", + Self::ModexpModOverflow => "modexp mod overflow", + Self::Bn128FieldPointNotAMember => "field point not a member of bn128 curve", + Self::Bn128AffineGFailedToCreate => "failed to create affine g point for bn128 curve", + Self::Bn128PairLength => "bn128 invalid pair length", + Self::BlobInvalidInputLength => "invalid blob input length", + Self::BlobMismatchedVersion => "mismatched blob version", + Self::BlobVerifyKzgProofFailed => "verifying blob kzg proof failed", + Self::Other(s) => s, + }; + f.write_str(s) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn stateful_precompile_mut() { + #[derive(Default, Clone)] + struct MyPrecompile {} + + impl StatefulPrecompileMut for MyPrecompile { + fn call_mut( + &mut self, + _bytes: &Bytes, + _gas_price: u64, + _env: &Env, + ) -> PrecompileResult { + PrecompileResult::Err(PrecompileError::OutOfGas) + } + } + + let mut p = Precompile::new_stateful_mut(MyPrecompile::default()); + match &mut p { + Precompile::StatefulMut(p) => { + let _ = p.call_mut(&Bytes::new(), 0, &Env::default()); + } + _ => panic!("not a state"), + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/result.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/result.md new file mode 100644 index 00000000..4bd534bb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/result.md @@ -0,0 +1,452 @@ +# ๐Ÿฆ€ result.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/result.rs) + +```rust +use crate::{Address, Bytes, Log, State, U256}; +use core::fmt; +use std::{boxed::Box, string::String, vec::Vec}; + +/// Result of EVM execution. +pub type EVMResult = EVMResultGeneric; + +/// Generic result of EVM execution. Used to represent error and generic output. +pub type EVMResultGeneric = core::result::Result>; + +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ResultAndState { + /// Status of execution + pub result: ExecutionResult, + /// State that got updated + pub state: State, +} + +/// Result of a transaction execution. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ExecutionResult { + /// Returned successfully + Success { + reason: SuccessReason, + gas_used: u64, + gas_refunded: u64, + logs: Vec, + output: Output, + }, + /// Reverted by `REVERT` opcode that doesn't spend all gas. + Revert { gas_used: u64, output: Bytes }, + /// Reverted for various reasons and spend all gas. + Halt { + reason: HaltReason, + /// Halting will spend all the gas, and will be equal to gas_limit. + gas_used: u64, + }, +} + +impl ExecutionResult { + /// Returns if transaction execution is successful. + /// 1 indicates success, 0 indicates revert. + /// + pub fn is_success(&self) -> bool { + matches!(self, Self::Success { .. }) + } + + /// Returns true if execution result is a Halt. + pub fn is_halt(&self) -> bool { + matches!(self, Self::Halt { .. }) + } + + /// Returns the output data of the execution. + /// + /// Returns `None` if the execution was halted. + pub fn output(&self) -> Option<&Bytes> { + match self { + Self::Success { output, .. } => Some(output.data()), + Self::Revert { output, .. } => Some(output), + _ => None, + } + } + + /// Consumes the type and returns the output data of the execution. + /// + /// Returns `None` if the execution was halted. + pub fn into_output(self) -> Option { + match self { + Self::Success { output, .. } => Some(output.into_data()), + Self::Revert { output, .. } => Some(output), + _ => None, + } + } + + /// Returns the logs if execution is successful, or an empty list otherwise. + pub fn logs(&self) -> &[Log] { + match self { + Self::Success { logs, .. } => logs, + _ => &[], + } + } + + /// Consumes `self` and returns the logs if execution is successful, or an empty list otherwise. + pub fn into_logs(self) -> Vec { + match self { + Self::Success { logs, .. } => logs, + _ => Vec::new(), + } + } + + /// Returns the gas used. + pub fn gas_used(&self) -> u64 { + match *self { + Self::Success { gas_used, .. } + | Self::Revert { gas_used, .. } + | Self::Halt { gas_used, .. } => gas_used, + } + } +} + +/// Output of a transaction execution. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum Output { + Call(Bytes), + Create(Bytes, Option
), +} + +impl Output { + /// Returns the output data of the execution output. + pub fn into_data(self) -> Bytes { + match self { + Output::Call(data) => data, + Output::Create(data, _) => data, + } + } + + /// Returns the output data of the execution output. + pub fn data(&self) -> &Bytes { + match self { + Output::Call(data) => data, + Output::Create(data, _) => data, + } + } + + /// Returns the created address, if any. + pub fn address(&self) -> Option<&Address> { + match self { + Output::Call(_) => None, + Output::Create(_, address) => address.as_ref(), + } + } +} + +/// Main EVM error. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum EVMError { + /// Transaction validation error. + Transaction(InvalidTransaction), + /// Header validation error. + Header(InvalidHeader), + /// Database error. + Database(DBError), + /// Custom error. + /// + /// Useful for handler registers where custom logic would want to return their own custom error. + Custom(String), +} + +#[cfg(feature = "std")] +impl std::error::Error for EVMError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Transaction(e) => Some(e), + Self::Header(e) => Some(e), + Self::Database(e) => Some(e), + Self::Custom(_) => None, + } + } +} + +impl fmt::Display for EVMError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Transaction(e) => write!(f, "transaction validation error: {e}"), + Self::Header(e) => write!(f, "header validation error: {e}"), + Self::Database(e) => write!(f, "database error: {e}"), + Self::Custom(e) => f.write_str(e), + } + } +} + +impl From for EVMError { + fn from(value: InvalidTransaction) -> Self { + Self::Transaction(value) + } +} + +impl From for EVMError { + fn from(value: InvalidHeader) -> Self { + Self::Header(value) + } +} + +/// Transaction validation error. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum InvalidTransaction { + /// When using the EIP-1559 fee model introduced in the London upgrade, transactions specify two primary fee fields: + /// - `gas_max_fee`: The maximum total fee a user is willing to pay, inclusive of both base fee and priority fee. + /// - `gas_priority_fee`: The extra amount a user is willing to give directly to the miner, often referred to as the "tip". + /// + /// Provided `gas_priority_fee` exceeds the total `gas_max_fee`. + PriorityFeeGreaterThanMaxFee, + /// EIP-1559: `gas_price` is less than `basefee`. + GasPriceLessThanBasefee, + /// `gas_limit` in the tx is bigger than `block_gas_limit`. + CallerGasLimitMoreThanBlock, + /// Initial gas for a Call is bigger than `gas_limit`. + /// + /// Initial gas for a Call contains: + /// - initial stipend gas + /// - gas for access list and input data + CallGasCostMoreThanGasLimit, + /// EIP-3607 Reject transactions from senders with deployed code + RejectCallerWithCode, + /// Transaction account does not have enough amount of ether to cover transferred value and gas_limit*gas_price. + LackOfFundForMaxFee { + fee: Box, + balance: Box, + }, + /// Overflow payment in transaction. + OverflowPaymentInTransaction, + /// Nonce overflows in transaction. + NonceOverflowInTransaction, + NonceTooHigh { + tx: u64, + state: u64, + }, + NonceTooLow { + tx: u64, + state: u64, + }, + /// EIP-3860: Limit and meter initcode + CreateInitCodeSizeLimit, + /// Transaction chain id does not match the config chain id. + InvalidChainId, + /// Access list is not supported for blocks before the Berlin hardfork. + AccessListNotSupported, + /// `max_fee_per_blob_gas` is not supported for blocks before the Cancun hardfork. + MaxFeePerBlobGasNotSupported, + /// `blob_hashes`/`blob_versioned_hashes` is not supported for blocks before the Cancun hardfork. + BlobVersionedHashesNotSupported, + /// Block `blob_gas_price` is greater than tx-specified `max_fee_per_blob_gas` after Cancun. + BlobGasPriceGreaterThanMax, + /// There should be at least one blob in Blob transaction. + EmptyBlobs, + /// Blob transaction can't be a create transaction. + /// `to` must be present + BlobCreateTransaction, + /// Transaction has more then [`crate::MAX_BLOB_NUMBER_PER_BLOCK`] blobs + TooManyBlobs, + /// Blob transaction contains a versioned hash with an incorrect version + BlobVersionNotSupported, + /// EOF TxCreate transaction is not supported before Prague hardfork. + EofInitcodesNotSupported, + /// EOF TxCreate transaction max initcode number reached. + EofInitcodesNumberLimit, + /// EOF initcode in TXCreate is too large. + EofInitcodesSizeLimit, + /// EOF crate should have `to` address + EofCrateShouldHaveToAddress, + /// System transactions are not supported post-regolith hardfork. + /// + /// Before the Regolith hardfork, there was a special field in the `Deposit` transaction + /// type that differentiated between `system` and `user` deposit transactions. This field + /// was deprecated in the Regolith hardfork, and this error is thrown if a `Deposit` transaction + /// is found with this field set to `true` after the hardfork activation. + /// + /// In addition, this error is internal, and bubbles up into a [HaltReason::FailedDeposit] error + /// in the `revm` handler for the consumer to easily handle. This is due to a state transition + /// rule on OP Stack chains where, if for any reason a deposit transaction fails, the transaction + /// must still be included in the block, the sender nonce is bumped, the `mint` value persists, and + /// special gas accounting rules are applied. Normally on L1, [EVMError::Transaction] errors + /// are cause for non-inclusion, so a special [HaltReason] variant was introduced to handle this + /// case for failed deposit transactions. + #[cfg(feature = "optimism")] + DepositSystemTxPostRegolith, + /// Deposit transaction haults bubble up to the global main return handler, wiping state and + /// only increasing the nonce + persisting the mint value. + /// + /// This is a catch-all error for any deposit transaction that is results in a [HaltReason] error + /// post-regolith hardfork. This allows for a consumer to easily handle special cases where + /// a deposit transaction fails during validation, but must still be included in the block. + /// + /// In addition, this error is internal, and bubbles up into a [HaltReason::FailedDeposit] error + /// in the `revm` handler for the consumer to easily handle. This is due to a state transition + /// rule on OP Stack chains where, if for any reason a deposit transaction fails, the transaction + /// must still be included in the block, the sender nonce is bumped, the `mint` value persists, and + /// special gas accounting rules are applied. Normally on L1, [EVMError::Transaction] errors + /// are cause for non-inclusion, so a special [HaltReason] variant was introduced to handle this + /// case for failed deposit transactions. + #[cfg(feature = "optimism")] + HaltedDepositPostRegolith, +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidTransaction {} + +impl fmt::Display for InvalidTransaction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::PriorityFeeGreaterThanMaxFee => { + write!(f, "priority fee is greater than max fee") + } + Self::GasPriceLessThanBasefee => { + write!(f, "gas price is less than basefee") + } + Self::CallerGasLimitMoreThanBlock => { + write!(f, "caller gas limit exceeds the block gas limit") + } + Self::CallGasCostMoreThanGasLimit => { + write!(f, "call gas cost exceeds the gas limit") + } + Self::RejectCallerWithCode => { + write!(f, "reject transactions from senders with deployed code") + } + Self::LackOfFundForMaxFee { fee, balance } => { + write!(f, "lack of funds ({balance}) for max fee ({fee})") + } + Self::OverflowPaymentInTransaction => { + write!(f, "overflow payment in transaction") + } + Self::NonceOverflowInTransaction => { + write!(f, "nonce overflow in transaction") + } + Self::NonceTooHigh { tx, state } => { + write!(f, "nonce {tx} too high, expected {state}") + } + Self::NonceTooLow { tx, state } => { + write!(f, "nonce {tx} too low, expected {state}") + } + Self::CreateInitCodeSizeLimit => { + write!(f, "create initcode size limit") + } + Self::InvalidChainId => write!(f, "invalid chain ID"), + Self::AccessListNotSupported => write!(f, "access list not supported"), + Self::MaxFeePerBlobGasNotSupported => { + write!(f, "max fee per blob gas not supported") + } + Self::BlobVersionedHashesNotSupported => { + write!(f, "blob versioned hashes not supported") + } + Self::BlobGasPriceGreaterThanMax => { + write!(f, "blob gas price is greater than max fee per blob gas") + } + Self::EmptyBlobs => write!(f, "empty blobs"), + Self::BlobCreateTransaction => write!(f, "blob create transaction"), + Self::TooManyBlobs => write!(f, "too many blobs"), + Self::BlobVersionNotSupported => write!(f, "blob version not supported"), + Self::EofInitcodesNotSupported => write!(f, "EOF initcodes not supported"), + Self::EofCrateShouldHaveToAddress => write!(f, "EOF crate should have `to` address"), + Self::EofInitcodesSizeLimit => write!(f, "EOF initcodes size limit"), + Self::EofInitcodesNumberLimit => write!(f, "EOF initcodes number limit"), + #[cfg(feature = "optimism")] + Self::DepositSystemTxPostRegolith => { + write!( + f, + "deposit system transactions post regolith hardfork are not supported" + ) + } + #[cfg(feature = "optimism")] + Self::HaltedDepositPostRegolith => { + write!( + f, + "deposit transaction halted post-regolith; error will be bubbled up to main return handler" + ) + } + } + } +} + +/// Errors related to misconfiguration of a [`crate::env::BlockEnv`]. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum InvalidHeader { + /// `prevrandao` is not set for Merge and above. + PrevrandaoNotSet, + /// `excess_blob_gas` is not set for Cancun and above. + ExcessBlobGasNotSet, +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidHeader {} + +impl fmt::Display for InvalidHeader { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::PrevrandaoNotSet => write!(f, "`prevrandao` not set"), + Self::ExcessBlobGasNotSet => write!(f, "`excess_blob_gas` not set"), + } + } +} + +/// Reason a transaction successfully completed. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum SuccessReason { + Stop, + Return, + SelfDestruct, +} + +/// Indicates that the EVM has experienced an exceptional halt. This causes execution to +/// immediately end with all gas being consumed. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum HaltReason { + OutOfGas(OutOfGasError), + OpcodeNotFound, + InvalidFEOpcode, + InvalidJump, + NotActivated, + StackUnderflow, + StackOverflow, + OutOfOffset, + CreateCollision, + PrecompileError, + NonceOverflow, + /// Create init code size exceeds limit (runtime). + CreateContractSizeLimit, + /// Error on created contract that begins with EF + CreateContractStartingWithEF, + /// EIP-3860: Limit and meter initcode. Initcode size limit exceeded. + CreateInitCodeSizeLimit, + + /* Internal Halts that can be only found inside Inspector */ + OverflowPayment, + StateChangeDuringStaticCall, + CallNotAllowedInsideStatic, + OutOfFunds, + CallTooDeep, + + /* Optimism errors */ + #[cfg(feature = "optimism")] + FailedDeposit, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum OutOfGasError { + // Basic OOG error + Basic, + // Tried to expand past REVM limit + MemoryLimit, + // Basic OOG error from memory expansion + Memory, + // Precompile threw OOG error + Precompile, + // When performing something that takes a U256 and casts down to a u64, if its too large this would fire + // i.e. in `as_usize_or_fail` + InvalidOperand, +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/specification.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/specification.md new file mode 100644 index 00000000..1e913628 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/specification.md @@ -0,0 +1,431 @@ +# ๐Ÿฆ€ specification.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/specification.rs) + +```rust +#![allow(non_camel_case_types)] + +pub use SpecId::*; + +/// Specification IDs and their activation block. +/// +/// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs) +#[cfg(not(feature = "optimism"))] +#[repr(u8)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum SpecId { + FRONTIER = 0, // Frontier 0 + FRONTIER_THAWING = 1, // Frontier Thawing 200000 + HOMESTEAD = 2, // Homestead 1150000 + DAO_FORK = 3, // DAO Fork 1920000 + TANGERINE = 4, // Tangerine Whistle 2463000 + SPURIOUS_DRAGON = 5, // Spurious Dragon 2675000 + BYZANTIUM = 6, // Byzantium 4370000 + CONSTANTINOPLE = 7, // Constantinople 7280000 is overwritten with PETERSBURG + PETERSBURG = 8, // Petersburg 7280000 + ISTANBUL = 9, // Istanbul 9069000 + MUIR_GLACIER = 10, // Muir Glacier 9200000 + BERLIN = 11, // Berlin 12244000 + LONDON = 12, // London 12965000 + ARROW_GLACIER = 13, // Arrow Glacier 13773000 + GRAY_GLACIER = 14, // Gray Glacier 15050000 + MERGE = 15, // Paris/Merge 15537394 (TTD: 58750000000000000000000) + SHANGHAI = 16, // Shanghai 17034870 (Timestamp: 1681338455) + CANCUN = 17, // Cancun 19426587 (Timestamp: 1710338135) + PRAGUE = 18, // Praque TBD + #[default] + LATEST = u8::MAX, +} + +/// Specification IDs and their activation block. +/// +/// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs) +#[cfg(feature = "optimism")] +#[repr(u8)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum SpecId { + FRONTIER = 0, + FRONTIER_THAWING = 1, + HOMESTEAD = 2, + DAO_FORK = 3, + TANGERINE = 4, + SPURIOUS_DRAGON = 5, + BYZANTIUM = 6, + CONSTANTINOPLE = 7, + PETERSBURG = 8, + ISTANBUL = 9, + MUIR_GLACIER = 10, + BERLIN = 11, + LONDON = 12, + ARROW_GLACIER = 13, + GRAY_GLACIER = 14, + MERGE = 15, + BEDROCK = 16, + REGOLITH = 17, + SHANGHAI = 18, + CANYON = 19, + CANCUN = 20, + ECOTONE = 21, + PRAGUE = 22, + #[default] + LATEST = u8::MAX, +} + +impl SpecId { + /// Returns the `SpecId` for the given `u8`. + #[inline] + pub fn try_from_u8(spec_id: u8) -> Option { + Self::n(spec_id) + } + + /// Returns `true` if the given specification ID is enabled in this spec. + #[inline] + pub const fn is_enabled_in(self, other: Self) -> bool { + Self::enabled(self, other) + } + + /// Returns `true` if the given specification ID is enabled in this spec. + #[inline] + pub const fn enabled(our: SpecId, other: SpecId) -> bool { + our as u8 >= other as u8 + } +} + +impl From<&str> for SpecId { + fn from(name: &str) -> Self { + match name { + "Frontier" => Self::FRONTIER, + "Homestead" => Self::HOMESTEAD, + "Tangerine" => Self::TANGERINE, + "Spurious" => Self::SPURIOUS_DRAGON, + "Byzantium" => Self::BYZANTIUM, + "Constantinople" => Self::CONSTANTINOPLE, + "Petersburg" => Self::PETERSBURG, + "Istanbul" => Self::ISTANBUL, + "MuirGlacier" => Self::MUIR_GLACIER, + "Berlin" => Self::BERLIN, + "London" => Self::LONDON, + "Merge" => Self::MERGE, + "Shanghai" => Self::SHANGHAI, + "Cancun" => Self::CANCUN, + "Prague" => Self::PRAGUE, + #[cfg(feature = "optimism")] + "Bedrock" => SpecId::BEDROCK, + #[cfg(feature = "optimism")] + "Regolith" => SpecId::REGOLITH, + #[cfg(feature = "optimism")] + "Canyon" => SpecId::CANYON, + #[cfg(feature = "optimism")] + "Ecotone" => SpecId::ECOTONE, + _ => Self::LATEST, + } + } +} + +impl From for &'static str { + fn from(spec_id: SpecId) -> Self { + match spec_id { + SpecId::FRONTIER => "Frontier", + SpecId::FRONTIER_THAWING => "Frontier Thawing", + SpecId::HOMESTEAD => "Homestead", + SpecId::DAO_FORK => "DAO Fork", + SpecId::TANGERINE => "Tangerine", + SpecId::SPURIOUS_DRAGON => "Spurious", + SpecId::BYZANTIUM => "Byzantium", + SpecId::CONSTANTINOPLE => "Constantinople", + SpecId::PETERSBURG => "Petersburg", + SpecId::ISTANBUL => "Istanbul", + SpecId::MUIR_GLACIER => "MuirGlacier", + SpecId::BERLIN => "Berlin", + SpecId::LONDON => "London", + SpecId::ARROW_GLACIER => "Arrow Glacier", + SpecId::GRAY_GLACIER => "Gray Glacier", + SpecId::MERGE => "Merge", + SpecId::SHANGHAI => "Shanghai", + SpecId::CANCUN => "Cancun", + SpecId::PRAGUE => "Prague", + #[cfg(feature = "optimism")] + SpecId::BEDROCK => "Bedrock", + #[cfg(feature = "optimism")] + SpecId::REGOLITH => "Regolith", + #[cfg(feature = "optimism")] + SpecId::CANYON => "Canyon", + #[cfg(feature = "optimism")] + SpecId::ECOTONE => "Ecotone", + SpecId::LATEST => "Latest", + } + } +} + +pub trait Spec: Sized + 'static { + /// The specification ID. + const SPEC_ID: SpecId; + + /// Returns `true` if the given specification ID is enabled in this spec. + #[inline] + fn enabled(spec_id: SpecId) -> bool { + SpecId::enabled(Self::SPEC_ID, spec_id) + } +} + +macro_rules! spec { + ($spec_id:ident, $spec_name:ident) => { + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct $spec_name; + + impl Spec for $spec_name { + const SPEC_ID: SpecId = $spec_id; + } + }; +} + +spec!(FRONTIER, FrontierSpec); +// FRONTIER_THAWING no EVM spec change +spec!(HOMESTEAD, HomesteadSpec); +// DAO_FORK no EVM spec change +spec!(TANGERINE, TangerineSpec); +spec!(SPURIOUS_DRAGON, SpuriousDragonSpec); +spec!(BYZANTIUM, ByzantiumSpec); +// CONSTANTINOPLE was overridden with PETERSBURG +spec!(PETERSBURG, PetersburgSpec); +spec!(ISTANBUL, IstanbulSpec); +// MUIR_GLACIER no EVM spec change +spec!(BERLIN, BerlinSpec); +spec!(LONDON, LondonSpec); +// ARROW_GLACIER no EVM spec change +// GRAY_GLACIER no EVM spec change +spec!(MERGE, MergeSpec); +spec!(SHANGHAI, ShanghaiSpec); +spec!(CANCUN, CancunSpec); +spec!(PRAGUE, PragueSpec); + +spec!(LATEST, LatestSpec); + +// Optimism Hardforks +#[cfg(feature = "optimism")] +spec!(BEDROCK, BedrockSpec); +#[cfg(feature = "optimism")] +spec!(REGOLITH, RegolithSpec); +#[cfg(feature = "optimism")] +spec!(CANYON, CanyonSpec); +#[cfg(feature = "optimism")] +spec!(ECOTONE, EcotoneSpec); + +#[macro_export] +macro_rules! spec_to_generic { + ($spec_id:expr, $e:expr) => {{ + // We are transitioning from var to generic spec. + match $spec_id { + $crate::SpecId::FRONTIER | SpecId::FRONTIER_THAWING => { + use $crate::FrontierSpec as SPEC; + $e + } + $crate::SpecId::HOMESTEAD | SpecId::DAO_FORK => { + use $crate::HomesteadSpec as SPEC; + $e + } + $crate::SpecId::TANGERINE => { + use $crate::TangerineSpec as SPEC; + $e + } + $crate::SpecId::SPURIOUS_DRAGON => { + use $crate::SpuriousDragonSpec as SPEC; + $e + } + $crate::SpecId::BYZANTIUM => { + use $crate::ByzantiumSpec as SPEC; + $e + } + $crate::SpecId::PETERSBURG | $crate::SpecId::CONSTANTINOPLE => { + use $crate::PetersburgSpec as SPEC; + $e + } + $crate::SpecId::ISTANBUL | $crate::SpecId::MUIR_GLACIER => { + use $crate::IstanbulSpec as SPEC; + $e + } + $crate::SpecId::BERLIN => { + use $crate::BerlinSpec as SPEC; + $e + } + $crate::SpecId::LONDON + | $crate::SpecId::ARROW_GLACIER + | $crate::SpecId::GRAY_GLACIER => { + use $crate::LondonSpec as SPEC; + $e + } + $crate::SpecId::MERGE => { + use $crate::MergeSpec as SPEC; + $e + } + $crate::SpecId::SHANGHAI => { + use $crate::ShanghaiSpec as SPEC; + $e + } + $crate::SpecId::CANCUN => { + use $crate::CancunSpec as SPEC; + $e + } + $crate::SpecId::LATEST => { + use $crate::LatestSpec as SPEC; + $e + } + $crate::SpecId::PRAGUE => { + use $crate::PragueSpec as SPEC; + $e + } + #[cfg(feature = "optimism")] + $crate::SpecId::BEDROCK => { + use $crate::BedrockSpec as SPEC; + $e + } + #[cfg(feature = "optimism")] + $crate::SpecId::REGOLITH => { + use $crate::RegolithSpec as SPEC; + $e + } + #[cfg(feature = "optimism")] + $crate::SpecId::CANYON => { + use $crate::CanyonSpec as SPEC; + $e + } + #[cfg(feature = "optimism")] + $crate::SpecId::ECOTONE => { + use $crate::EcotoneSpec as SPEC; + $e + } + } + }}; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn spec_to_generic() { + use SpecId::*; + + spec_to_generic!(FRONTIER, assert_eq!(SPEC::SPEC_ID, FRONTIER)); + spec_to_generic!(FRONTIER_THAWING, assert_eq!(SPEC::SPEC_ID, FRONTIER)); + spec_to_generic!(HOMESTEAD, assert_eq!(SPEC::SPEC_ID, HOMESTEAD)); + spec_to_generic!(DAO_FORK, assert_eq!(SPEC::SPEC_ID, HOMESTEAD)); + spec_to_generic!(TANGERINE, assert_eq!(SPEC::SPEC_ID, TANGERINE)); + spec_to_generic!(SPURIOUS_DRAGON, assert_eq!(SPEC::SPEC_ID, SPURIOUS_DRAGON)); + spec_to_generic!(BYZANTIUM, assert_eq!(SPEC::SPEC_ID, BYZANTIUM)); + spec_to_generic!(CONSTANTINOPLE, assert_eq!(SPEC::SPEC_ID, PETERSBURG)); + spec_to_generic!(PETERSBURG, assert_eq!(SPEC::SPEC_ID, PETERSBURG)); + spec_to_generic!(ISTANBUL, assert_eq!(SPEC::SPEC_ID, ISTANBUL)); + spec_to_generic!(MUIR_GLACIER, assert_eq!(SPEC::SPEC_ID, ISTANBUL)); + spec_to_generic!(BERLIN, assert_eq!(SPEC::SPEC_ID, BERLIN)); + spec_to_generic!(LONDON, assert_eq!(SPEC::SPEC_ID, LONDON)); + spec_to_generic!(ARROW_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON)); + spec_to_generic!(GRAY_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON)); + spec_to_generic!(MERGE, assert_eq!(SPEC::SPEC_ID, MERGE)); + #[cfg(feature = "optimism")] + spec_to_generic!(BEDROCK, assert_eq!(SPEC::SPEC_ID, BEDROCK)); + #[cfg(feature = "optimism")] + spec_to_generic!(REGOLITH, assert_eq!(SPEC::SPEC_ID, REGOLITH)); + spec_to_generic!(SHANGHAI, assert_eq!(SPEC::SPEC_ID, SHANGHAI)); + #[cfg(feature = "optimism")] + spec_to_generic!(CANYON, assert_eq!(SPEC::SPEC_ID, CANYON)); + spec_to_generic!(CANCUN, assert_eq!(SPEC::SPEC_ID, CANCUN)); + spec_to_generic!(PRAGUE, assert_eq!(SPEC::SPEC_ID, PRAGUE)); + spec_to_generic!(LATEST, assert_eq!(SPEC::SPEC_ID, LATEST)); + } +} + +#[cfg(feature = "optimism")] +#[cfg(test)] +mod optimism_tests { + use super::*; + + #[test] + fn test_bedrock_post_merge_hardforks() { + assert!(BedrockSpec::enabled(SpecId::MERGE)); + assert!(!BedrockSpec::enabled(SpecId::SHANGHAI)); + assert!(!BedrockSpec::enabled(SpecId::CANCUN)); + assert!(!BedrockSpec::enabled(SpecId::LATEST)); + assert!(BedrockSpec::enabled(SpecId::BEDROCK)); + assert!(!BedrockSpec::enabled(SpecId::REGOLITH)); + } + + #[test] + fn test_regolith_post_merge_hardforks() { + assert!(RegolithSpec::enabled(SpecId::MERGE)); + assert!(!RegolithSpec::enabled(SpecId::SHANGHAI)); + assert!(!RegolithSpec::enabled(SpecId::CANCUN)); + assert!(!RegolithSpec::enabled(SpecId::LATEST)); + assert!(RegolithSpec::enabled(SpecId::BEDROCK)); + assert!(RegolithSpec::enabled(SpecId::REGOLITH)); + } + + #[test] + fn test_bedrock_post_merge_hardforks_spec_id() { + assert!(SpecId::enabled(SpecId::BEDROCK, SpecId::MERGE)); + assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::SHANGHAI)); + assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::CANCUN)); + assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::LATEST)); + assert!(SpecId::enabled(SpecId::BEDROCK, SpecId::BEDROCK)); + assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::REGOLITH)); + } + + #[test] + fn test_regolith_post_merge_hardforks_spec_id() { + assert!(SpecId::enabled(SpecId::REGOLITH, SpecId::MERGE)); + assert!(!SpecId::enabled(SpecId::REGOLITH, SpecId::SHANGHAI)); + assert!(!SpecId::enabled(SpecId::REGOLITH, SpecId::CANCUN)); + assert!(!SpecId::enabled(SpecId::REGOLITH, SpecId::LATEST)); + assert!(SpecId::enabled(SpecId::REGOLITH, SpecId::BEDROCK)); + assert!(SpecId::enabled(SpecId::REGOLITH, SpecId::REGOLITH)); + } + + #[test] + fn test_canyon_post_merge_hardforks() { + assert!(CanyonSpec::enabled(SpecId::MERGE)); + assert!(CanyonSpec::enabled(SpecId::SHANGHAI)); + assert!(!CanyonSpec::enabled(SpecId::CANCUN)); + assert!(!CanyonSpec::enabled(SpecId::LATEST)); + assert!(CanyonSpec::enabled(SpecId::BEDROCK)); + assert!(CanyonSpec::enabled(SpecId::REGOLITH)); + assert!(CanyonSpec::enabled(SpecId::CANYON)); + } + + #[test] + fn test_canyon_post_merge_hardforks_spec_id() { + assert!(SpecId::enabled(SpecId::CANYON, SpecId::MERGE)); + assert!(SpecId::enabled(SpecId::CANYON, SpecId::SHANGHAI)); + assert!(!SpecId::enabled(SpecId::CANYON, SpecId::CANCUN)); + assert!(!SpecId::enabled(SpecId::CANYON, SpecId::LATEST)); + assert!(SpecId::enabled(SpecId::CANYON, SpecId::BEDROCK)); + assert!(SpecId::enabled(SpecId::CANYON, SpecId::REGOLITH)); + assert!(SpecId::enabled(SpecId::CANYON, SpecId::CANYON)); + } + + #[test] + fn test_ecotone_post_merge_hardforks() { + assert!(EcotoneSpec::enabled(SpecId::MERGE)); + assert!(EcotoneSpec::enabled(SpecId::SHANGHAI)); + assert!(EcotoneSpec::enabled(SpecId::CANCUN)); + assert!(!EcotoneSpec::enabled(SpecId::LATEST)); + assert!(EcotoneSpec::enabled(SpecId::BEDROCK)); + assert!(EcotoneSpec::enabled(SpecId::REGOLITH)); + assert!(EcotoneSpec::enabled(SpecId::CANYON)); + assert!(EcotoneSpec::enabled(SpecId::ECOTONE)); + } + + #[test] + fn test_ecotone_post_merge_hardforks_spec_id() { + assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::MERGE)); + assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::SHANGHAI)); + assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::CANCUN)); + assert!(!SpecId::enabled(SpecId::ECOTONE, SpecId::LATEST)); + assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::BEDROCK)); + assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::REGOLITH)); + assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::CANYON)); + assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::ECOTONE)); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/state.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/state.md new file mode 100644 index 00000000..e4d20a82 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/state.md @@ -0,0 +1,357 @@ +# ๐Ÿฆ€ state.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/state.rs) + +```rust +use crate::{Address, Bytecode, HashMap, B256, KECCAK_EMPTY, U256}; +use bitflags::bitflags; +use core::hash::{Hash, Hasher}; + +/// EVM State is a mapping from addresses to accounts. +pub type State = HashMap; + +/// Structure used for EIP-1153 transient storage. +pub type TransientStorage = HashMap<(Address, U256), U256>; + +/// An account's Storage is a mapping from 256-bit integer keys to [StorageSlot]s. +pub type Storage = HashMap; + +#[derive(Debug, Clone, PartialEq, Eq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Account { + /// Balance, nonce, and code. + pub info: AccountInfo, + /// Storage cache + pub storage: Storage, + /// Account status flags. + pub status: AccountStatus, +} + +// The `bitflags!` macro generates `struct`s that manage a set of flags. +bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[cfg_attr(feature = "serde", serde(transparent))] + pub struct AccountStatus: u8 { + /// When account is loaded but not touched or interacted with. + /// This is the default state. + const Loaded = 0b00000000; + /// When account is newly created we will not access database + /// to fetch storage values + const Created = 0b00000001; + /// If account is marked for self destruction. + const SelfDestructed = 0b00000010; + /// Only when account is marked as touched we will save it to database. + const Touched = 0b00000100; + /// used only for pre spurious dragon hardforks where existing and empty were two separate states. + /// it became same state after EIP-161: State trie clearing + const LoadedAsNotExisting = 0b0001000; + } +} + +impl Default for AccountStatus { + fn default() -> Self { + Self::Loaded + } +} + +impl Account { + /// Create new account and mark it as non existing. + pub fn new_not_existing() -> Self { + Self { + info: AccountInfo::default(), + storage: HashMap::new(), + status: AccountStatus::LoadedAsNotExisting, + } + } + + /// Mark account as self destructed. + pub fn mark_selfdestruct(&mut self) { + self.status |= AccountStatus::SelfDestructed; + } + + /// Unmark account as self destructed. + pub fn unmark_selfdestruct(&mut self) { + self.status -= AccountStatus::SelfDestructed; + } + + /// Is account marked for self destruct. + pub fn is_selfdestructed(&self) -> bool { + self.status.contains(AccountStatus::SelfDestructed) + } + + /// Mark account as touched + pub fn mark_touch(&mut self) { + self.status |= AccountStatus::Touched; + } + + /// Unmark the touch flag. + pub fn unmark_touch(&mut self) { + self.status -= AccountStatus::Touched; + } + + /// If account status is marked as touched. + pub fn is_touched(&self) -> bool { + self.status.contains(AccountStatus::Touched) + } + + /// Mark account as newly created. + pub fn mark_created(&mut self) { + self.status |= AccountStatus::Created; + } + + /// Unmark created flag. + pub fn unmark_created(&mut self) { + self.status -= AccountStatus::Created; + } + + /// Is account loaded as not existing from database + /// This is needed for pre spurious dragon hardforks where + /// existing and empty were two separate states. + pub fn is_loaded_as_not_existing(&self) -> bool { + self.status.contains(AccountStatus::LoadedAsNotExisting) + } + + /// Is account newly created in this transaction. + pub fn is_created(&self) -> bool { + self.status.contains(AccountStatus::Created) + } + + /// Is account empty, check if nonce and balance are zero and code is empty. + pub fn is_empty(&self) -> bool { + self.info.is_empty() + } + + /// Returns an iterator over the storage slots that have been changed. + /// + /// See also [StorageSlot::is_changed] + pub fn changed_storage_slots(&self) -> impl Iterator { + self.storage.iter().filter(|(_, slot)| slot.is_changed()) + } +} + +impl From for Account { + fn from(info: AccountInfo) -> Self { + Self { + info, + storage: HashMap::new(), + status: AccountStatus::Loaded, + } + } +} + +/// This type keeps track of the current value of a storage slot. +#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct StorageSlot { + /// The value of the storage slot before it was changed. + /// + /// When the slot is first loaded, this is the original value. + /// + /// If the slot was not changed, this is equal to the present value. + pub previous_or_original_value: U256, + /// When loaded with sload present value is set to original value + pub present_value: U256, +} + +impl StorageSlot { + /// Creates a new _unchanged_ `StorageSlot` for the given value. + pub fn new(original: U256) -> Self { + Self { + previous_or_original_value: original, + present_value: original, + } + } + + /// Creates a new _changed_ `StorageSlot`. + pub fn new_changed(previous_or_original_value: U256, present_value: U256) -> Self { + Self { + previous_or_original_value, + present_value, + } + } + + /// Returns true if the present value differs from the original value + pub fn is_changed(&self) -> bool { + self.previous_or_original_value != self.present_value + } + + /// Returns the original value of the storage slot. + pub fn original_value(&self) -> U256 { + self.previous_or_original_value + } + + /// Returns the current value of the storage slot. + pub fn present_value(&self) -> U256 { + self.present_value + } +} + +/// AccountInfo account information. +#[derive(Clone, Debug, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AccountInfo { + /// Account balance. + pub balance: U256, + /// Account nonce. + pub nonce: u64, + /// code hash, + pub code_hash: B256, + /// code: if None, `code_by_hash` will be used to fetch it if code needs to be loaded from + /// inside of `revm`. + pub code: Option, +} + +impl Default for AccountInfo { + fn default() -> Self { + Self { + balance: U256::ZERO, + code_hash: KECCAK_EMPTY, + code: Some(Bytecode::default()), + nonce: 0, + } + } +} + +impl PartialEq for AccountInfo { + fn eq(&self, other: &Self) -> bool { + self.balance == other.balance + && self.nonce == other.nonce + && self.code_hash == other.code_hash + } +} + +impl Hash for AccountInfo { + fn hash(&self, state: &mut H) { + self.balance.hash(state); + self.nonce.hash(state); + self.code_hash.hash(state); + } +} + +impl AccountInfo { + pub fn new(balance: U256, nonce: u64, code_hash: B256, code: Bytecode) -> Self { + Self { + balance, + nonce, + code: Some(code), + code_hash, + } + } + + /// Returns account info without the code. + pub fn without_code(mut self) -> Self { + self.take_bytecode(); + self + } + + /// Returns if an account is empty. + /// + /// An account is empty if the following conditions are met. + /// - code hash is zero or set to the Keccak256 hash of the empty string `""` + /// - balance is zero + /// - nonce is zero + pub fn is_empty(&self) -> bool { + let code_empty = self.is_empty_code_hash() || self.code_hash == B256::ZERO; + code_empty && self.balance == U256::ZERO && self.nonce == 0 + } + + /// Returns `true` if the account is not empty. + pub fn exists(&self) -> bool { + !self.is_empty() + } + + /// Returns `true` if account has no nonce and code. + pub fn has_no_code_and_nonce(&self) -> bool { + self.is_empty_code_hash() && self.nonce == 0 + } + + /// Return bytecode hash associated with this account. + /// If account does not have code, it return's `KECCAK_EMPTY` hash. + pub fn code_hash(&self) -> B256 { + self.code_hash + } + + /// Returns true if the code hash is the Keccak256 hash of the empty string `""`. + #[inline] + pub fn is_empty_code_hash(&self) -> bool { + self.code_hash == KECCAK_EMPTY + } + + /// Take bytecode from account. Code will be set to None. + pub fn take_bytecode(&mut self) -> Option { + self.code.take() + } + + pub fn from_balance(balance: U256) -> Self { + AccountInfo { + balance, + ..Default::default() + } + } +} + +#[cfg(test)] +mod tests { + use crate::{Account, KECCAK_EMPTY, U256}; + + #[test] + fn account_is_empty_balance() { + let mut account = Account::default(); + assert!(account.is_empty()); + + account.info.balance = U256::from(1); + assert!(!account.is_empty()); + + account.info.balance = U256::ZERO; + assert!(account.is_empty()); + } + + #[test] + fn account_is_empty_nonce() { + let mut account = Account::default(); + assert!(account.is_empty()); + + account.info.nonce = 1; + assert!(!account.is_empty()); + + account.info.nonce = 0; + assert!(account.is_empty()); + } + + #[test] + fn account_is_empty_code_hash() { + let mut account = Account::default(); + assert!(account.is_empty()); + + account.info.code_hash = [1; 32].into(); + assert!(!account.is_empty()); + + account.info.code_hash = [0; 32].into(); + assert!(account.is_empty()); + + account.info.code_hash = KECCAK_EMPTY; + assert!(account.is_empty()); + } + + #[test] + fn account_state() { + let mut account = Account::default(); + + assert!(!account.is_touched()); + assert!(!account.is_selfdestructed()); + + account.mark_touch(); + assert!(account.is_touched()); + assert!(!account.is_selfdestructed()); + + account.mark_selfdestruct(); + assert!(account.is_touched()); + assert!(account.is_selfdestructed()); + + account.unmark_selfdestruct(); + assert!(account.is_touched()); + assert!(!account.is_selfdestructed()); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/primitives/src/utilities.md b/docs/revm-python-spec/revm-verif/revm/primitives/src/utilities.md new file mode 100644 index 00000000..66560775 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/primitives/src/utilities.md @@ -0,0 +1,176 @@ +# ๐Ÿฆ€ utilities.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/primitives/src/utilities.rs) + +```rust +use crate::{ + b256, B256, BLOB_GASPRICE_UPDATE_FRACTION, MIN_BLOB_GASPRICE, TARGET_BLOB_GAS_PER_BLOCK, +}; +pub use alloy_primitives::keccak256; + +/// The Keccak-256 hash of the empty string `""`. +pub const KECCAK_EMPTY: B256 = + b256!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); + +/// Calculates the `excess_blob_gas` from the parent header's `blob_gas_used` and `excess_blob_gas`. +/// +/// See also [the EIP-4844 helpers] +/// (`calc_excess_blob_gas`). +#[inline] +pub fn calc_excess_blob_gas(parent_excess_blob_gas: u64, parent_blob_gas_used: u64) -> u64 { + (parent_excess_blob_gas + parent_blob_gas_used).saturating_sub(TARGET_BLOB_GAS_PER_BLOCK) +} + +/// Calculates the blob gas price from the header's excess blob gas field. +/// +/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers) +/// (`get_blob_gasprice`). +#[inline] +pub fn calc_blob_gasprice(excess_blob_gas: u64) -> u128 { + fake_exponential( + MIN_BLOB_GASPRICE, + excess_blob_gas, + BLOB_GASPRICE_UPDATE_FRACTION, + ) +} + +/// Approximates `factor * e ** (numerator / denominator)` using Taylor expansion. +/// +/// This is used to calculate the blob price. +/// +/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers) +/// (`fake_exponential`). +/// +/// # Panics +/// +/// This function panics if `denominator` is zero. +#[inline] +pub fn fake_exponential(factor: u64, numerator: u64, denominator: u64) -> u128 { + assert_ne!(denominator, 0, "attempt to divide by zero"); + let factor = factor as u128; + let numerator = numerator as u128; + let denominator = denominator as u128; + + let mut i = 1; + let mut output = 0; + let mut numerator_accum = factor * denominator; + while numerator_accum > 0 { + output += numerator_accum; + + // Denominator is asserted as not zero at the start of the function. + numerator_accum = (numerator_accum * numerator) / (denominator * i); + i += 1; + } + output / denominator +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::GAS_PER_BLOB; + + // https://github.com/ethereum/go-ethereum/blob/28857080d732857030eda80c69b9ba2c8926f221/consensus/misc/eip4844/eip4844_test.go#L27 + #[test] + fn test_calc_excess_blob_gas() { + for t @ &(excess, blobs, expected) in &[ + // The excess blob gas should not increase from zero if the used blob + // slots are below - or equal - to the target. + (0, 0, 0), + (0, 1, 0), + (0, TARGET_BLOB_GAS_PER_BLOCK / GAS_PER_BLOB, 0), + // If the target blob gas is exceeded, the excessBlobGas should increase + // by however much it was overshot + ( + 0, + (TARGET_BLOB_GAS_PER_BLOCK / GAS_PER_BLOB) + 1, + GAS_PER_BLOB, + ), + ( + 1, + (TARGET_BLOB_GAS_PER_BLOCK / GAS_PER_BLOB) + 1, + GAS_PER_BLOB + 1, + ), + ( + 1, + (TARGET_BLOB_GAS_PER_BLOCK / GAS_PER_BLOB) + 2, + 2 * GAS_PER_BLOB + 1, + ), + // The excess blob gas should decrease by however much the target was + // under-shot, capped at zero. + ( + TARGET_BLOB_GAS_PER_BLOCK, + TARGET_BLOB_GAS_PER_BLOCK / GAS_PER_BLOB, + TARGET_BLOB_GAS_PER_BLOCK, + ), + ( + TARGET_BLOB_GAS_PER_BLOCK, + (TARGET_BLOB_GAS_PER_BLOCK / GAS_PER_BLOB) - 1, + TARGET_BLOB_GAS_PER_BLOCK - GAS_PER_BLOB, + ), + ( + TARGET_BLOB_GAS_PER_BLOCK, + (TARGET_BLOB_GAS_PER_BLOCK / GAS_PER_BLOB) - 2, + TARGET_BLOB_GAS_PER_BLOCK - (2 * GAS_PER_BLOB), + ), + ( + GAS_PER_BLOB - 1, + (TARGET_BLOB_GAS_PER_BLOCK / GAS_PER_BLOB) - 1, + 0, + ), + ] { + let actual = calc_excess_blob_gas(excess, blobs * GAS_PER_BLOB); + assert_eq!(actual, expected, "test: {t:?}"); + } + } + + // https://github.com/ethereum/go-ethereum/blob/28857080d732857030eda80c69b9ba2c8926f221/consensus/misc/eip4844/eip4844_test.go#L60 + #[test] + fn test_calc_blob_fee() { + let blob_fee_vectors = &[ + (0, 1), + (2314057, 1), + (2314058, 2), + (10 * 1024 * 1024, 23), + // calc_blob_gasprice approximates `e ** (excess_blob_gas / BLOB_GASPRICE_UPDATE_FRACTION)` using Taylor expansion + // + // to roughly find where boundaries will be hit: + // 2 ** bits = e ** (excess_blob_gas / BLOB_GASPRICE_UPDATE_FRACTION) + // excess_blob_gas = ln(2 ** bits) * BLOB_GASPRICE_UPDATE_FRACTION + (148099578, 18446739238971471609), // output is just below the overflow + (148099579, 18446744762204311910), // output is just after the overflow + (161087488, 902580055246494526580), + ]; + + for &(excess, expected) in blob_fee_vectors { + let actual = calc_blob_gasprice(excess); + assert_eq!(actual, expected, "test: {excess}"); + } + } + + // https://github.com/ethereum/go-ethereum/blob/28857080d732857030eda80c69b9ba2c8926f221/consensus/misc/eip4844/eip4844_test.go#L78 + #[test] + fn fake_exp() { + for t @ &(factor, numerator, denominator, expected) in &[ + (1u64, 0u64, 1u64, 1u128), + (38493, 0, 1000, 38493), + (0, 1234, 2345, 0), + (1, 2, 1, 6), // approximate 7.389 + (1, 4, 2, 6), + (1, 3, 1, 16), // approximate 20.09 + (1, 6, 2, 18), + (1, 4, 1, 49), // approximate 54.60 + (1, 8, 2, 50), + (10, 8, 2, 542), // approximate 540.598 + (11, 8, 2, 596), // approximate 600.58 + (1, 5, 1, 136), // approximate 148.4 + (1, 5, 2, 11), // approximate 12.18 + (2, 5, 2, 23), // approximate 24.36 + (1, 50000000, 2225652, 5709098764), + (1, 380928, BLOB_GASPRICE_UPDATE_FRACTION, 1), + ] { + let actual = fake_exponential(factor, numerator, denominator); + assert_eq!(actual, expected, "test: {t:?}"); + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/benches/bench.md b/docs/revm-python-spec/revm-verif/revm/revm/benches/bench.md new file mode 100644 index 00000000..cdde026f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/benches/bench.md @@ -0,0 +1,145 @@ +# ๐Ÿฆ€ bench.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/benches/bench.rs) + +```rust +use criterion::{ + criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, +}; +use revm::{ + db::BenchmarkDB, + interpreter::{analysis::to_analysed, Contract, DummyHost, Interpreter}, + primitives::{address, bytes, hex, BerlinSpec, Bytecode, Bytes, TransactTo, U256}, + Evm, +}; +use revm_interpreter::{opcode::make_instruction_table, SharedMemory, EMPTY_SHARED_MEMORY}; +use std::time::Duration; + +fn analysis(c: &mut Criterion) { + let evm = Evm::builder() + .modify_tx_env(|tx| { + tx.caller = address!("0000000000000000000000000000000000000002"); + tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + // evm.env.tx.data = bytes!("30627b7c"); + tx.data = bytes!("8035F0CE"); + }) + .build(); + + let contract_data: Bytes = hex::decode(ANALYSIS).unwrap().into(); + + let mut g = c.benchmark_group("analysis"); + g.noise_threshold(0.03) + .warm_up_time(Duration::from_secs(3)) + .measurement_time(Duration::from_secs(10)) + .sample_size(10); + + let raw = Bytecode::new_raw(contract_data.clone()); + let mut evm = evm + .modify() + .reset_handler_with_db(BenchmarkDB::new_bytecode(raw)) + .build(); + bench_transact(&mut g, &mut evm); + + let checked = Bytecode::new_raw(contract_data.clone()); + let mut evm = evm + .modify() + .reset_handler_with_db(BenchmarkDB::new_bytecode(checked)) + .build(); + bench_transact(&mut g, &mut evm); + + let analysed = to_analysed(Bytecode::new_raw(contract_data)); + let mut evm = evm + .modify() + .reset_handler_with_db(BenchmarkDB::new_bytecode(analysed)) + .build(); + bench_transact(&mut g, &mut evm); + + g.finish(); +} + +fn snailtracer(c: &mut Criterion) { + let mut evm = Evm::builder() + .with_db(BenchmarkDB::new_bytecode(bytecode(SNAILTRACER))) + .modify_tx_env(|tx| { + tx.caller = address!("1000000000000000000000000000000000000000"); + tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.data = bytes!("30627b7c"); + }) + .build(); + + let mut g = c.benchmark_group("snailtracer"); + g.noise_threshold(0.03) + .warm_up_time(Duration::from_secs(3)) + .measurement_time(Duration::from_secs(10)) + .sample_size(10); + bench_transact(&mut g, &mut evm); + bench_eval(&mut g, &mut evm); + g.finish(); +} + +fn transfer(c: &mut Criterion) { + let mut evm = Evm::builder() + .with_db(BenchmarkDB::new_bytecode(Bytecode::new())) + .modify_tx_env(|tx| { + tx.caller = address!("0000000000000000000000000000000000000001"); + tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.value = U256::from(10); + }) + .build(); + + let mut g = c.benchmark_group("transfer"); + g.noise_threshold(0.03).warm_up_time(Duration::from_secs(1)); + bench_transact(&mut g, &mut evm); + g.finish(); +} + +fn bench_transact(g: &mut BenchmarkGroup<'_, WallTime>, evm: &mut Evm<'_, EXT, BenchmarkDB>) { + let state = match evm.context.evm.db.0 { + Bytecode::LegacyRaw(_) => "raw", + Bytecode::LegacyAnalyzed(_) => "analysed", + Bytecode::Eof(_) => "eof", + }; + let id = format!("transact/{state}"); + g.bench_function(id, |b| b.iter(|| evm.transact().unwrap())); +} + +fn bench_eval(g: &mut BenchmarkGroup<'_, WallTime>, evm: &mut Evm<'static, (), BenchmarkDB>) { + g.bench_function("eval", |b| { + let contract = Contract { + input: evm.context.evm.env.tx.data.clone(), + bytecode: to_analysed(evm.context.evm.db.0.clone()), + ..Default::default() + }; + let mut shared_memory = SharedMemory::new(); + let mut host = DummyHost::new(*evm.context.evm.env.clone()); + let instruction_table = make_instruction_table::(); + b.iter(move || { + // replace memory with empty memory to use it inside interpreter. + // Later return memory back. + let temp = core::mem::replace(&mut shared_memory, EMPTY_SHARED_MEMORY); + let mut interpreter = Interpreter::new(contract.clone(), u64::MAX, false); + let res = interpreter.run(temp, &instruction_table, &mut host); + shared_memory = interpreter.take_memory(); + host.clear(); + res + }) + }); +} + +fn bytecode(s: &str) -> Bytecode { + to_analysed(Bytecode::new_raw(hex::decode(s).unwrap().into())) +} + +#[rustfmt::skip] +criterion_group!( + benches, + analysis, + snailtracer, + transfer, +); +criterion_main!(benches); + +const ANALYSIS: &str = "6060604052341561000f57600080fd5b604051610dd1380380610dd18339810160405280805190602001909190805182019190602001805190602001909190805182019190505083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508360008190555082600390805190602001906100a79291906100e3565b5081600460006101000a81548160ff021916908360ff16021790555080600590805190602001906100d99291906100e3565b5050505050610188565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061012457805160ff1916838001178555610152565b82800160010185558215610152579182015b82811115610151578251825591602001919060010190610136565b5b50905061015f9190610163565b5090565b61018591905b80821115610181576000816000905550600101610169565b5090565b90565b610c3a806101976000396000f3006060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014257806318160ddd1461019c57806323b872dd146101c557806327e235e31461023e578063313ce5671461028b5780635c658165146102ba57806370a082311461032657806395d89b4114610373578063a9059cbb14610401578063dd62ed3e1461045b575b600080fd5b34156100bf57600080fd5b6100c76104c7565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101075780820151818401526020810190506100ec565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014d57600080fd5b610182600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610565565b604051808215151515815260200191505060405180910390f35b34156101a757600080fd5b6101af610657565b6040518082815260200191505060405180910390f35b34156101d057600080fd5b610224600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061065d565b604051808215151515815260200191505060405180910390f35b341561024957600080fd5b610275600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506108f7565b6040518082815260200191505060405180910390f35b341561029657600080fd5b61029e61090f565b604051808260ff1660ff16815260200191505060405180910390f35b34156102c557600080fd5b610310600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610922565b6040518082815260200191505060405180910390f35b341561033157600080fd5b61035d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610947565b6040518082815260200191505060405180910390f35b341561037e57600080fd5b610386610990565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c65780820151818401526020810190506103ab565b50505050905090810190601f1680156103f35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561040c57600080fd5b610441600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a2e565b604051808215151515815260200191505060405180910390f35b341561046657600080fd5b6104b1600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b87565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561055d5780601f106105325761010080835404028352916020019161055d565b820191906000526020600020905b81548152906001019060200180831161054057829003601f168201915b505050505081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561072e5750828110155b151561073957600080fd5b82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156108865782600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b60016020528060005260406000206000915090505481565b600460009054906101000a900460ff1681565b6002602052816000526040600020602052806000526040600020600091509150505481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a265780601f106109fb57610100808354040283529160200191610a26565b820191906000526020600020905b815481529060010190602001808311610a0957829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7e57600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a72305820df254047bc8f2904ad3e966b6db116d703bebd40efadadb5e738c836ffc8f58a0029"; + +const SNAILTRACER: &str = "608060405234801561001057600080fd5b506004361061004c5760003560e01c806330627b7c1461005157806375ac892a14610085578063784f13661461011d578063c294360114610146575b600080fd5b610059610163565b604080516001600160f81b03199485168152928416602084015292168183015290519081900360600190f35b6100a86004803603604081101561009b57600080fd5b50803590602001356102d1565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100e25781810151838201526020016100ca565b50505050905090810190601f16801561010f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100596004803603606081101561013357600080fd5b508035906020810135906040013561055b565b6100a86004803603602081101561015c57600080fd5b5035610590565b6000806000610176610400610300610834565b60405180606001604052806001546000546207d5dc028161019357fe5b058152600060208083018290526040928301919091528251600b81905583820151600c81905593830151600d819055835160608082018652928152808401959095528484015282519081018352600654815260075491810191909152600854918101919091526102259161021c916102139161020e91612ef7565b612f64565b6207d5dc612feb565b620f424061301e565b8051600e556020810151600f55604001516010556102416142dd565b61025a816102556102006101806008613064565b613212565b90506102708161025561014561021c6008613064565b905061028481610255610258806008613064565b905061029a8161025561020a61020c6008613064565b90506102a781600461301e565b90506102b1613250565b8051602082015160409092015160f891821b9692821b9550901b92509050565b606060005b6000548112156104c95760006102ed828686613064565b90506002816000015160f81b90808054603f811680603e811461032a576002830184556001831661031c578192505b600160028404019350610342565b600084815260209081902060ff198516905560419094555b505050600190038154600116156103685790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816020015160f81b90808054603f811680603e81146103c557600283018455600183166103b7578192505b6001600284040193506103dd565b600084815260209081902060ff198516905560419094555b505050600190038154600116156104035790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816040015160f81b90808054603f811680603e81146104605760028301845560018316610452578192505b600160028404019350610478565b600084815260209081902060ff198516905560419094555b5050506001900381546001161561049e5790600052602060002090602091828204019190065b815460ff601f929092036101000a9182021916600160f81b90930402919091179055506001016102d6565b506002805460408051602060018416156101000260001901909316849004601f8101849004840282018401909252818152929183018282801561054d5780601f106105225761010080835404028352916020019161054d565b820191906000526020600020905b81548152906001019060200180831161053057829003601f168201915b505050505090505b92915050565b60008060008061056c878787613064565b8051602082015160409092015160f891821b9a92821b9950901b9650945050505050565b600154606090600019015b600081126107a35760005b6000548112156107995760006105bd828487613064565b90506002816000015160f81b90808054603f811680603e81146105fa57600283018455600183166105ec578192505b600160028404019350610612565b600084815260209081902060ff198516905560419094555b505050600190038154600116156106385790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816020015160f81b90808054603f811680603e81146106955760028301845560018316610687578192505b6001600284040193506106ad565b600084815260209081902060ff198516905560419094555b505050600190038154600116156106d35790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816040015160f81b90808054603f811680603e81146107305760028301845560018316610722578192505b600160028404019350610748565b600084815260209081902060ff198516905560419094555b5050506001900381546001161561076e5790600052602060002090602091828204019190065b815460ff601f929092036101000a9182021916600160f81b90930402919091179055506001016105a6565b506000190161059b565b506002805460408051602060018416156101000260001901909316849004601f810184900484028201840190925281815292918301828280156108275780601f106107fc57610100808354040283529160200191610827565b820191906000526020600020905b81548152906001019060200180831161080a57829003601f168201915b505050505090505b919050565b8160008190555080600181905550604051806080016040528060405180606001604052806302faf08081526020016303197500815260200163119e7f8081525081526020016108a460405180606001604052806000815260200161a673198152602001620f423f19815250612f64565b815260006020808301829052604092830182905283518051600355808201516004558301516005558381015180516006559081015160075582015160085582820151600955606092830151600a805460ff1916911515919091179055815192830190915260015490548291906207d5dc028161091c57fe5b058152600060208083018290526040928301919091528251600b81905583820151600c81905593830151600d819055835160608082018652928152808401959095528484015282519081018352600654815260075491810191909152600854918101919091526109979161021c916102139161020e91612ef7565b8051600e55602080820151600f55604091820151601055815160a08101835264174876e8008152825160608082018552641748862a40825263026e8f00828501526304dd1e008286015282840191825284518082018652600080825281860181905281870181905284870191825286518084018852620b71b081526203d09081880181905281890152928501928352608085018181526011805460018082018355919093528651600b9093027f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c688101938455955180517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c69880155808901517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6a8801558901517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6b870155925180517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6c870155808801517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6d8701558801517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6e860155925180517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6f860155958601517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c7085015594909501517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c71830155517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c72909101805492949192909160ff1990911690836002811115610c1057fe5b0217905550505060116040518060a0016040528064174876e8008152602001604051806060016040528064174290493f19815260200163026e8f0081526020016304dd1e008152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806203d09081526020016203d0908152602001620b71b0815250815260200160006002811115610cb657fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff1990921691908490811115610d5857fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200163026e8f00815260200164174876e800815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620b71b08152602001620b71b08152602001620b71b0815250815260200160006002811115610dfd57fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff1990921691908490811115610e9f57fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200163026e8f00815260200164173e54e97f1981525081526020016040518060600160405280600081526020016000815260200160008152508152602001604051806060016040528060008152602001600081526020016000815250815260200160006002811115610f3f57fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff1990921691908490811115610fe157fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200164174876e80081526020016304dd1e00815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620b71b08152602001620b71b08152602001620b71b081525081526020016000600281111561108657fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff199092169190849081111561112857fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200164174399c9ff1981526020016304dd1e00815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620b71b08152602001620b71b08152602001620b71b08152508152602001600060028111156111ce57fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff199092169190849081111561127057fe5b0217905550505060116040518060a0016040528062fbc5208152602001604051806060016040528063019bfcc0815260200162fbc52081526020016302cd29c0815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561131157fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff19909216919084908111156113b357fe5b0217905550505060116040518060a001604052806323c34600815260200160405180606001604052806302faf080815260200163289c455081526020016304dd1e008152508152602001604051806060016040528062b71b00815260200162b71b00815260200162b71b00815250815260200160405180606001604052806000815260200160008152602001600081525081526020016000600281111561145657fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff19909216919084908111156114f857fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016305a1f4a081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561160c57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff19909216919084908111156116fd57fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016305a1f4a08152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561180e57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff19909216919084908111156118ff57fe5b0217905550505060126040518060e001604052806040518060600160405280630555a9608152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016305a1f4a08152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115611a1357fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115611b0457fe5b0217905550505060126040518060e001604052806040518060600160405280630555a960815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016305a1f4a081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115611c1557fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115611d0657fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016303aa6a608152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115611e1a57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115611f0b57fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016303aa6a6081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561201c57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561210d57fe5b0217905550505060126040518060e001604052806040518060600160405280630555a9608152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016303aa6a6081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561222157fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561231257fe5b0217905550505060126040518060e001604052806040518060600160405280630555a960815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016303aa6a608152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561242357fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561251457fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016303aa6a6081525081526020016040518060600160405280630555a9608152602001630188c2e081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561262857fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561271957fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630555a9608152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016305a1f4a08152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561282d57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561291e57fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630555a960815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016303aa6a608152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115612a3257fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115612b2357fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016305a1f4a081525081526020016040518060600160405280630555a960815260200163016a8c8081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115612c3757fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115612d2857fe5b0217905550505060005b601254811015612ef257600060128281548110612d4b57fe5b600091825260209182902060408051610140810182526013909302909101805460e08401908152600182015461010085015260028083015461012086015290845282516060818101855260038401548252600484015482880152600584015482860152858701919091528351808201855260068401548152600784015481880152600884015481860152858501528351808201855260098401548152600a84015481880152600b840154818601528186015283518082018552600c8401548152600d84015481880152600e84015481860152608086015283519081018452600f830154815260108301549581019590955260118201549285019290925260a0830193909352601283015491929160c084019160ff90911690811115612e6c57fe5b6002811115612e7757fe5b815250509050612eac61020e612e95836020015184600001516132cd565b612ea7846040015185600001516132cd565b612ef7565b60128381548110612eb957fe5b60009182526020918290208351600960139093029091019182015590820151600a820155604090910151600b9091015550600101612d32565b505050565b612eff6142dd565b604051806060016040528083602001518560400151028460400151866020015102038152602001836040015185600001510284600001518660400151020381526020018360000151856020015102846020015186600001510203815250905092915050565b612f6c6142dd565b604082015160208301518351600092612f9292918002918002919091019080020161330c565b90506040518060600160405280828560000151620f42400281612fb157fe5b058152602001828560200151620f42400281612fc957fe5b058152602001828560400151620f42400281612fe157fe5b0590529392505050565b612ff36142dd565b5060408051606081018252835183028152602080850151840290820152928101519091029082015290565b6130266142dd565b60405180606001604052808385600001518161303e57fe5b0581526020018385602001518161305157fe5b05815260200183856040015181612fe157fe5b61306c6142dd565b6000546013805463ffffffff1916918502860163ffffffff169190911790556130936142dd565b905060005b828112156131f157600061317261314c61021c613115600b60405180606001604052908160008201548152602001600182015481526020016002820154815250506207a1206000546207a1206130ec613343565b63ffffffff16816130f957fe5b0663ffffffff168d620f424002018161310e57fe5b0503612feb565b60408051606081018252600e548152600f5460208201526010549181019190915260015461025591906207a12090816130ec613343565b604080516060810182526006548152600754602082015260085491810191909152613212565b6040805160e081019091526003546080820190815260045460a083015260055460c083015291925060009181906131ae9061025586608c612feb565b81526020016131bc84612f64565b815260006020820181905260409091015290506131e5846102556131df8461336c565b8861301e565b93505050600101613098565b5061320861021c61320183613753565b60ff612feb565b90505b9392505050565b61321a6142dd565b50604080516060810182528251845101815260208084015181860151019082015291810151928101519092019181019190915290565b60008080556001819055613266906002906142fe565b60006003819055600481905560058190556006819055600781905560088190556009819055600a805460ff19169055600b819055600c819055600d819055600e819055600f81905560108190556132bf90601190614345565b6132cb60126000614366565b565b6132d56142dd565b5060408051606081018252825184510381526020808401518186015103908201528282015184830151039181019190915292915050565b80600260018201055b8181121561333d5780915060028182858161332c57fe5b05018161333557fe5b059050613315565b50919050565b6013805463ffffffff19811663ffffffff9182166341c64e6d0261303901821617918290551690565b6133746142dd565b600a826040015113156133a657604051806060016040528060008152602001600081526020016000815250905061082f565b60008060006133b48561379f565b91945092509050826133e857604051806060016040528060008152602001600081526020016000815250935050505061082f565b6133f0614387565b6133f86143c7565b6134006142dd565b6134086142dd565b600086600181111561341657fe5b1415613505576011858154811061342957fe5b60009182526020918290206040805160a081018252600b90930290910180548352815160608082018452600183015482526002808401548388015260038401548386015285870192909252835180820185526004840154815260058401548188015260068401548186015285850152835180820185526007840154815260088401549681019690965260098301549386019390935291830193909352600a830154919291608084019160ff909116908111156134e157fe5b60028111156134ec57fe5b8152505093508360600151915083604001519050613653565b6012858154811061351257fe5b600091825260209182902060408051610140810182526013909302909101805460e08401908152600182015461010085015260028083015461012086015290845282516060818101855260038401548252600484015482880152600584015482860152858701919091528351808201855260068401548152600784015481880152600884015481860152858501528351808201855260098401548152600a84015481880152600b840154818601528186015283518082018552600c8401548152600d84015481880152600e84015481860152608086015283519081018452600f830154815260108301549581019590955260118201549285019290925260a0830193909352601283015491929160c084019160ff9091169081111561363357fe5b600281111561363e57fe5b8152505092508260a001519150826080015190505b6040820151600190811215613669575060408201515b808360200151131561367c575060208201515b808360400151131561368f575060408201515b60408a01805160010190819052600512156136f75780620f42406136b1613343565b63ffffffff16816136be57fe5b0663ffffffff1612156136e8576136e16136db84620f4240612feb565b8261301e565b92506136f7565b50965061082f95505050505050565b6136ff6142dd565b600088600181111561370d57fe5b14156137255761371e8b878b613a57565b9050613733565b6137308b868b613aec565b90505b6137448361025561021c8785613baa565b9b9a5050505050505050505050565b61375b6142dd565b60405180606001604052806137738460000151613be8565b81526020016137858460200151613be8565b81526020016137978460400151613be8565b905292915050565b60008080808080805b6011548110156138c2576000613890601183815481106137c457fe5b60009182526020918290206040805160a081018252600b90930290910180548352815160608082018452600183015482526002808401548388015260038401548386015285870192909252835180820185526004840154815260058401548188015260068401548186015285850152835180820185526007840154815260088401549681019690965260098301549386019390935291830193909352600a830154919291608084019160ff9091169081111561387c57fe5b600281111561388757fe5b9052508a613c13565b90506000811380156138a957508415806138a957508481125b156138b957809450600093508192505b506001016137a8565b5060005b601254811015613a49576000613a17601283815481106138e257fe5b600091825260209182902060408051610140810182526013909302909101805460e08401908152600182015461010085015260028083015461012086015290845282516060818101855260038401548252600484015482880152600584015482860152858701919091528351808201855260068401548152600784015481880152600884015481860152858501528351808201855260098401548152600a84015481880152600b840154818601528186015283518082018552600c8401548152600d84015481880152600e84015481860152608086015283519081018452600f830154815260108301549581019590955260118201549285019290925260a0830193909352601283015491929160c084019160ff90911690811115613a0357fe5b6002811115613a0e57fe5b9052508a613cbb565b9050600081138015613a305750841580613a3057508481125b15613a4057809450600193508192505b506001016138c6565b509196909550909350915050565b613a5f6142dd565b6000613a7a856000015161025561021c886020015187612feb565b90506000613a8f61020e8387602001516132cd565b9050600085608001516002811115613aa357fe5b1415613ae1576000613ab9828860200151613e0c565b12613acd57613aca81600019612feb565b90505b613ad8868383613e31565b9250505061320b565b613ad8868383613fc1565b613af46142dd565b6000613b0f856000015161025561021c886020015187612feb565b6060860151909150620a2c2a9015613b2757506216e3605b6000620f4240613b3f87606001518960200151613e0c565b81613b4657fe5b05905060008112613b55576000035b64e8d4a5100081800281038380020281900590036000811215613b8c57613b8188858960600151613fc1565b94505050505061320b565b613b9e88858960600151868686614039565b98975050505050505050565b613bb26142dd565b50604080516060810182528251845102815260208084015181860151029082015291810151928101519092029181019190915290565b600080821215613bfa5750600061082f565b620f4240821315613c0f5750620f424061082f565b5090565b600080613c28846020015184600001516132cd565b90506000620f4240613c3e838660200151613e0c565b81613c4557fe5b865191900591506000908002613c5b8480613e0c565b838402030190506000811215613c775760009350505050610555565b613c808161330c565b90506103e88183031315613c9957900391506105559050565b6103e88183011315613caf570191506105559050565b50600095945050505050565b600080613cd0846020015185600001516132cd565b90506000613ce6856040015186600001516132cd565b90506000613cf8856020015183612ef7565b90506000620f4240613d0a8584613e0c565b81613d1157fe5b0590506103e71981138015613d2757506103e881125b15613d39576000945050505050610555565b85518751600091613d49916132cd565b9050600082613d588386613e0c565b81613d5f57fe5b0590506000811280613d735750620f424081135b15613d875760009650505050505050610555565b6000613d938388612ef7565b9050600084613da68b6020015184613e0c565b81613dad57fe5b0590506000811280613dc35750620f4240818401135b15613dd957600098505050505050505050610555565b600085613de68985613e0c565b81613ded57fe5b0590506103e88112156137445760009950505050505050505050610555565b6040808201519083015160208084015190850151845186510291020191020192915050565b613e396142dd565b6000620f424080613e48613343565b63ffffffff1681613e5557fe5b0663ffffffff16625fdfb00281613e6857fe5b0590506000620f4240613e79613343565b63ffffffff1681613e8657fe5b0663ffffffff1690506000613e9a8261330c565b6103e8029050613ea86142dd565b620186a0613eb98760000151614216565b1315613ee657604051806060016040528060008152602001620f4240815260200160008152509050613f09565b6040518060600160405280620f4240815260200160008152602001600081525090505b613f1661020e8288612ef7565b90506000613f2761020e8884612ef7565b9050613f7f61020e613f64613f5285620f424088613f448c61422e565b0281613f4c57fe5b05612feb565b61025585620f424089613f448d61424e565b6102558a613f7689620f42400361330c565b6103e802612feb565b9150613fb460405180608001604052808a81526020018481526020018b6040015181526020018b60600151151581525061336c565b9998505050505050505050565b613fc96142dd565b6000613ffb61020e8660200151613ff686620f4240613fec898c60200151613e0c565b60020281613f4c57fe5b6132cd565b90506140306040518060800160405280868152602001838152602001876040015181526020018760600151151581525061336c565b95945050505050565b6140416142dd565b60608701516000199015614053575060015b600061408961020e61021c61406c8c602001518a612feb565b613ff68b6140798a61330c565b620f42408c8e0205018802612feb565b60608a0151909150620f42408601906140ba57620f42406140aa838a613e0c565b816140b157fe5b05620f42400390505b60408a0151619c406c0c9f2c9cd04674edea40000000620ea6008480028502850285020205019060021261415e5761412a61411f60405180608001604052808d81526020018681526020018e6040015181526020018e6060015115151581525061336c565b82620f424003612feb565b92506141448361025561413e8e8e8e613fc1565b84612feb565b925061415383620f424061301e565b94505050505061420c565b600281056203d09001620f4240614173613343565b63ffffffff168161418057fe5b0663ffffffff1612156141b2576141536141a461419e8d8d8d613fc1565b83612feb565b600283056203d0900161301e565b6142056141f76141ec60405180608001604052808e81526020018781526020018f6040015181526020018f6060015115151581525061336c565b83620f424003612feb565b60028305620b71b00361301e565b9450505050505b9695505050505050565b60008082131561422757508061082f565b5060000390565b60008061423a8361424e565b905061320b81820264e8d4a510000361330c565b60005b600082121561426757625fdfb082019150614251565b5b625fdfb0821261427f57625fdfb082039150614268565b6001828160025b818313156142d457818385028161429957fe5b0585019450620f4240808788860202816142af57fe5b05816142b757fe5b600095909503940592506001810181029190910290600201614286565b50505050919050565b60405180606001604052806000815260200160008152602001600081525090565b50805460018160011615610100020316600290046000825580601f106143245750614342565b601f0160209004906000526020600020908101906143429190614401565b50565b50805460008255600b02906000526020600020908101906143429190614416565b50805460008255601302906000526020600020908101906143429190614475565b6040518060a00160405280600081526020016143a16142dd565b81526020016143ae6142dd565b81526020016143bb6142dd565b81526020016000905290565b6040518060e001604052806143da6142dd565b81526020016143e76142dd565b81526020016143f46142dd565b81526020016143a16142dd565b5b80821115613c0f5760008155600101614402565b5b80821115613c0f57600080825560018201819055600282018190556003820181905560048201819055600582018190556006820181905560078201819055600882018190556009820155600a8101805460ff19169055600b01614417565b5b80821115613c0f576000808255600182018190556002820181905560038201819055600482018190556005820181905560068201819055600782018190556008820181905560098201819055600a8201819055600b8201819055600c8201819055600d8201819055600e8201819055600f820181905560108201819055601182015560128101805460ff1916905560130161447656fea2646970667358221220037024f5647853879c58fbcc61ac3616455f6f731cc6e84f91eb5a3b4e06c00464736f6c63430007060033"; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/builder.md b/docs/revm-python-spec/revm-verif/revm/revm/src/builder.md new file mode 100644 index 00000000..c1a58088 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/builder.md @@ -0,0 +1,651 @@ +# ๐Ÿฆ€ builder.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/builder.rs) + +```rust +use crate::{ + db::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}, + handler::register, + primitives::{ + BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, HandlerCfg, SpecId, TxEnv, + }, + Context, ContextWithHandlerCfg, Evm, Handler, +}; +use core::marker::PhantomData; +use std::boxed::Box; + +/// Evm Builder allows building or modifying EVM. +/// Note that some of the methods that changes underlying structures +/// will reset the registered handler to default mainnet. +pub struct EvmBuilder<'a, BuilderStage, EXT, DB: Database> { + context: Context, + /// Handler that will be used by EVM. It contains handle registers + handler: Handler<'a, Evm<'a, EXT, DB>, EXT, DB>, + /// Phantom data to mark the stage of the builder. + phantom: PhantomData, +} + +/// First stage of the builder allows setting generic variables. +/// Generic variables are database and external context. +pub struct SetGenericStage; + +/// Second stage of the builder allows appending handler registers. +/// Requires the database and external context to be set. +pub struct HandlerStage; + +impl<'a> Default for EvmBuilder<'a, SetGenericStage, (), EmptyDB> { + fn default() -> Self { + cfg_if::cfg_if! { + if #[cfg(all(feature = "optimism-default-handler", + not(feature = "negate-optimism-default-handler")))] { + let mut handler_cfg = HandlerCfg::new(SpecId::LATEST); + // set is_optimism to true by default. + handler_cfg.is_optimism = true; + + } else { + let handler_cfg = HandlerCfg::new(SpecId::LATEST); + } + } + + Self { + context: Context::default(), + handler: EvmBuilder::<'a, SetGenericStage, (), EmptyDB>::handler(handler_cfg), + phantom: PhantomData, + } + } +} + +impl<'a, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, EXT, DB> { + /// Sets the [`EmptyDB`] as the [`Database`] that will be used by [`Evm`]. + pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, EXT, EmptyDB> { + EvmBuilder { + context: Context::new( + self.context.evm.with_db(EmptyDB::default()), + self.context.external, + ), + handler: EvmBuilder::<'a, SetGenericStage, EXT, EmptyDB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + /// Sets the [`Database`] that will be used by [`Evm`]. + pub fn with_db(self, db: ODB) -> EvmBuilder<'a, SetGenericStage, EXT, ODB> { + EvmBuilder { + context: Context::new(self.context.evm.with_db(db), self.context.external), + handler: EvmBuilder::<'a, SetGenericStage, EXT, ODB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + /// Sets the [`DatabaseRef`] that will be used by [`Evm`]. + pub fn with_ref_db( + self, + db: ODB, + ) -> EvmBuilder<'a, SetGenericStage, EXT, WrapDatabaseRef> { + EvmBuilder { + context: Context::new( + self.context.evm.with_db(WrapDatabaseRef(db)), + self.context.external, + ), + handler: EvmBuilder::<'a, SetGenericStage, EXT, WrapDatabaseRef>::handler( + self.handler.cfg(), + ), + phantom: PhantomData, + } + } + + /// Sets the external context that will be used by [`Evm`]. + pub fn with_external_context( + self, + external: OEXT, + ) -> EvmBuilder<'a, SetGenericStage, OEXT, DB> { + EvmBuilder { + context: Context::new(self.context.evm, external), + handler: EvmBuilder::<'a, SetGenericStage, OEXT, DB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + + /// Sets Builder with [`EnvWithHandlerCfg`]. + pub fn with_env_with_handler_cfg( + mut self, + env_with_handler_cfg: EnvWithHandlerCfg, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + let EnvWithHandlerCfg { env, handler_cfg } = env_with_handler_cfg; + self.context.evm.env = env; + EvmBuilder { + context: self.context, + handler: EvmBuilder::<'a, HandlerStage, EXT, DB>::handler(handler_cfg), + phantom: PhantomData, + } + } + + /// Sets Builder with [`ContextWithHandlerCfg`]. + pub fn with_context_with_handler_cfg( + self, + context_with_handler_cfg: ContextWithHandlerCfg, + ) -> EvmBuilder<'a, HandlerStage, OEXT, ODB> { + EvmBuilder { + context: context_with_handler_cfg.context, + handler: EvmBuilder::<'a, HandlerStage, OEXT, ODB>::handler( + context_with_handler_cfg.cfg, + ), + phantom: PhantomData, + } + } + + /// Sets Builder with [`CfgEnvWithHandlerCfg`]. + pub fn with_cfg_env_with_handler_cfg( + mut self, + cfg_env_and_spec_id: CfgEnvWithHandlerCfg, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.context.evm.env.cfg = cfg_env_and_spec_id.cfg_env; + + EvmBuilder { + context: self.context, + handler: EvmBuilder::<'a, HandlerStage, EXT, DB>::handler( + cfg_env_and_spec_id.handler_cfg, + ), + phantom: PhantomData, + } + } + + /// Sets Builder with [`HandlerCfg`] + pub fn with_handler_cfg( + self, + handler_cfg: HandlerCfg, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + EvmBuilder { + context: self.context, + handler: EvmBuilder::<'a, HandlerStage, EXT, DB>::handler(handler_cfg), + phantom: PhantomData, + } + } + + /// Sets the Optimism handler with latest spec. + /// + /// If `optimism-default-handler` feature is enabled this is not needed. + #[cfg(feature = "optimism")] + pub fn optimism(mut self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.handler = Handler::optimism_with_spec(self.handler.cfg.spec_id); + EvmBuilder { + context: self.context, + handler: self.handler, + phantom: PhantomData, + } + } + + /// Sets the mainnet handler with latest spec. + /// + /// Enabled only with `optimism-default-handler` feature. + #[cfg(feature = "optimism-default-handler")] + pub fn mainnet(mut self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.handler = Handler::mainnet_with_spec(self.handler.cfg.spec_id); + EvmBuilder { + context: self.context, + handler: self.handler, + phantom: PhantomData, + } + } +} + +impl<'a, EXT, DB: Database> EvmBuilder<'a, HandlerStage, EXT, DB> { + /// Creates new builder from Evm, Evm is consumed and all field are moved to Builder. + /// It will preserve set handler and context. + /// + /// Builder is in HandlerStage and both database and external are set. + pub fn new(evm: Evm<'a, EXT, DB>) -> Self { + Self { + context: evm.context, + handler: evm.handler, + phantom: PhantomData, + } + } + + /// Sets the [`EmptyDB`] and resets the [`Handler`] to default mainnet. + pub fn reset_handler_with_empty_db(self) -> EvmBuilder<'a, HandlerStage, EXT, EmptyDB> { + EvmBuilder { + context: Context::new( + self.context.evm.with_db(EmptyDB::default()), + self.context.external, + ), + handler: EvmBuilder::<'a, HandlerStage, EXT, EmptyDB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + + /// Resets the [`Handler`] and sets base mainnet handler. + /// + /// Enabled only with `optimism-default-handler` feature. + #[cfg(feature = "optimism-default-handler")] + pub fn reset_handler_with_mainnet(mut self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.handler = Handler::mainnet_with_spec(self.handler.cfg.spec_id); + EvmBuilder { + context: self.context, + handler: self.handler, + phantom: PhantomData, + } + } + + /// Sets the [`Database`] that will be used by [`Evm`] + /// and resets the [`Handler`] to default mainnet. + pub fn reset_handler_with_db( + self, + db: ODB, + ) -> EvmBuilder<'a, SetGenericStage, EXT, ODB> { + EvmBuilder { + context: Context::new(self.context.evm.with_db(db), self.context.external), + handler: EvmBuilder::<'a, SetGenericStage, EXT, ODB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } + + /// Resets [`Handler`] and sets the [`DatabaseRef`] that will be used by [`Evm`] + /// and resets the [`Handler`] to default mainnet. + pub fn reset_handler_with_ref_db( + self, + db: ODB, + ) -> EvmBuilder<'a, SetGenericStage, EXT, WrapDatabaseRef> { + EvmBuilder { + context: Context::new( + self.context.evm.with_db(WrapDatabaseRef(db)), + self.context.external, + ), + handler: EvmBuilder::<'a, SetGenericStage, EXT, WrapDatabaseRef>::handler( + self.handler.cfg(), + ), + phantom: PhantomData, + } + } + + /// Resets [`Handler`] and sets new `ExternalContext` type. + /// and resets the [`Handler`] to default mainnet. + pub fn reset_handler_with_external_context( + self, + external: OEXT, + ) -> EvmBuilder<'a, SetGenericStage, OEXT, DB> { + EvmBuilder { + context: Context::new(self.context.evm, external), + handler: EvmBuilder::<'a, SetGenericStage, OEXT, DB>::handler(self.handler.cfg()), + phantom: PhantomData, + } + } +} + +impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB> { + /// Creates the default handler. + /// + /// This is useful for adding optimism handle register. + fn handler(handler_cfg: HandlerCfg) -> Handler<'a, Evm<'a, EXT, DB>, EXT, DB> { + Handler::new(handler_cfg) + } + + /// This modifies the [EvmBuilder] to make it easy to construct an [`Evm`] with a _specific_ + /// handler. + /// + /// # Example + /// ```rust + /// use revm::{EvmBuilder, Handler, primitives::{SpecId, HandlerCfg}}; + /// use revm_interpreter::primitives::CancunSpec; + /// let builder = EvmBuilder::default(); + /// + /// // get the desired handler + /// let mainnet = Handler::mainnet::(); + /// let builder = builder.with_handler(mainnet); + /// + /// // build the EVM + /// let evm = builder.build(); + /// ``` + pub fn with_handler( + self, + handler: Handler<'a, Evm<'a, EXT, DB>, EXT, DB>, + ) -> EvmBuilder<'a, BuilderStage, EXT, DB> { + EvmBuilder { + context: self.context, + handler, + phantom: PhantomData, + } + } + + /// Builds the [`Evm`]. + pub fn build(self) -> Evm<'a, EXT, DB> { + Evm::new(self.context, self.handler) + } + + /// Register Handler that modifies the behavior of EVM. + /// Check [`Handler`] for more information. + /// + /// When called, EvmBuilder will transition from SetGenericStage to HandlerStage. + pub fn append_handler_register( + mut self, + handle_register: register::HandleRegister, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.handler + .append_handler_register(register::HandleRegisters::Plain(handle_register)); + EvmBuilder { + context: self.context, + handler: self.handler, + + phantom: PhantomData, + } + } + + /// Register Handler that modifies the behavior of EVM. + /// Check [`Handler`] for more information. + /// + /// When called, EvmBuilder will transition from SetGenericStage to HandlerStage. + pub fn append_handler_register_box( + mut self, + handle_register: register::HandleRegisterBox, + ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.handler + .append_handler_register(register::HandleRegisters::Box(handle_register)); + EvmBuilder { + context: self.context, + handler: self.handler, + + phantom: PhantomData, + } + } + + /// Sets specification Id , that will mark the version of EVM. + /// It represent the hard fork of ethereum. + /// + /// # Note + /// + /// When changed it will reapply all handle registers, this can be + /// expensive operation depending on registers. + pub fn with_spec_id(mut self, spec_id: SpecId) -> Self { + self.handler.modify_spec_id(spec_id); + EvmBuilder { + context: self.context, + handler: self.handler, + + phantom: PhantomData, + } + } + + /// Allows modification of Evm Database. + pub fn modify_db(mut self, f: impl FnOnce(&mut DB)) -> Self { + f(&mut self.context.evm.db); + self + } + + /// Allows modification of external context. + pub fn modify_external_context(mut self, f: impl FnOnce(&mut EXT)) -> Self { + f(&mut self.context.external); + self + } + + /// Allows modification of Evm Environment. + pub fn modify_env(mut self, f: impl FnOnce(&mut Box)) -> Self { + f(&mut self.context.evm.env); + self + } + + /// Sets Evm Environment. + pub fn with_env(mut self, env: Box) -> Self { + self.context.evm.env = env; + self + } + + /// Allows modification of Evm's Transaction Environment. + pub fn modify_tx_env(mut self, f: impl FnOnce(&mut TxEnv)) -> Self { + f(&mut self.context.evm.env.tx); + self + } + + /// Sets Evm's Transaction Environment. + pub fn with_tx_env(mut self, tx_env: TxEnv) -> Self { + self.context.evm.env.tx = tx_env; + self + } + + /// Allows modification of Evm's Block Environment. + pub fn modify_block_env(mut self, f: impl FnOnce(&mut BlockEnv)) -> Self { + f(&mut self.context.evm.env.block); + self + } + + /// Sets Evm's Block Environment. + pub fn with_block_env(mut self, block_env: BlockEnv) -> Self { + self.context.evm.env.block = block_env; + self + } + + /// Allows modification of Evm's Config Environment. + pub fn modify_cfg_env(mut self, f: impl FnOnce(&mut CfgEnv)) -> Self { + f(&mut self.context.evm.env.cfg); + self + } + + /// Clears Environment of EVM. + pub fn with_clear_env(mut self) -> Self { + self.context.evm.env.clear(); + self + } + + /// Clears Transaction environment of EVM. + pub fn with_clear_tx_env(mut self) -> Self { + self.context.evm.env.tx.clear(); + self + } + /// Clears Block environment of EVM. + pub fn with_clear_block_env(mut self) -> Self { + self.context.evm.env.block.clear(); + self + } + + /// Resets [`Handler`] to default mainnet. + pub fn reset_handler(mut self) -> Self { + self.handler = Self::handler(self.handler.cfg()); + self + } +} + +#[cfg(test)] +mod test { + use super::SpecId; + use crate::{ + db::EmptyDB, + inspector::inspector_handle_register, + inspectors::NoOpInspector, + primitives::{ + address, AccountInfo, Address, Bytecode, Bytes, PrecompileResult, TransactTo, U256, + }, + Context, ContextPrecompile, ContextStatefulPrecompile, Evm, InMemoryDB, InnerEvmContext, + }; + use revm_interpreter::{gas, Host, Interpreter}; + use std::{cell::RefCell, rc::Rc, sync::Arc}; + + /// Custom evm context + #[derive(Default, Clone, Debug)] + pub(crate) struct CustomContext { + pub(crate) inner: Rc>, + } + + #[test] + fn simple_add_stateful_instruction() { + let code = Bytecode::new_raw([0xEF, 0x00].into()); + let code_hash = code.hash_slow(); + let to_addr = address!("ffffffffffffffffffffffffffffffffffffffff"); + + // initialize the custom context and make sure it's zero + let custom_context = CustomContext::default(); + assert_eq!(*custom_context.inner.borrow(), 0); + + let to_capture = custom_context.clone(); + let mut evm = Evm::builder() + .with_db(InMemoryDB::default()) + .modify_db(|db| { + db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) + }) + .modify_tx_env(|tx| tx.transact_to = TransactTo::Call(to_addr)) + // we need to use handle register box to capture the custom context in the handle + // register + .append_handler_register_box(Box::new(move |handler| { + let custom_context = to_capture.clone(); + + // we need to use a box to capture the custom context in the instruction + let custom_instruction = Box::new( + move |_interp: &mut Interpreter, _host: &mut Evm<'_, (), InMemoryDB>| { + // modify the value + let mut inner = custom_context.inner.borrow_mut(); + *inner += 1; + }, + ); + + // need to make esure the instruction table is a boxed instruction table so that we + // can insert the custom instruction as a boxed instruction + let mut table = handler.take_instruction_table(); + table = table.map(|mut table| { + // now we can finally insert + table.insert_boxed(0xEF, custom_instruction); + table + }); + handler.instruction_table = table; + })) + .build(); + + let _result_and_state = evm.transact().unwrap(); + + // ensure the custom context was modified + assert_eq!(*custom_context.inner.borrow(), 1); + } + + #[test] + fn simple_add_instruction() { + const CUSTOM_INSTRUCTION_COST: u64 = 133; + const INITIAL_TX_GAS: u64 = 21000; + const EXPECTED_RESULT_GAS: u64 = INITIAL_TX_GAS + CUSTOM_INSTRUCTION_COST; + + fn custom_instruction(interp: &mut Interpreter, _host: &mut impl Host) { + // just spend some gas + gas!(interp, CUSTOM_INSTRUCTION_COST); + } + + let code = Bytecode::new_raw([0xEF, 0x00].into()); + let code_hash = code.hash_slow(); + let to_addr = address!("ffffffffffffffffffffffffffffffffffffffff"); + + let mut evm = Evm::builder() + .with_db(InMemoryDB::default()) + .modify_db(|db| { + db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) + }) + .modify_tx_env(|tx| tx.transact_to = TransactTo::Call(to_addr)) + .append_handler_register(|handler| { + if let Some(ref mut table) = handler.instruction_table { + table.insert(0xEF, custom_instruction) + } + }) + .build(); + + let result_and_state = evm.transact().unwrap(); + assert_eq!(result_and_state.result.gas_used(), EXPECTED_RESULT_GAS); + } + + #[test] + fn simple_build() { + // build without external with latest spec + Evm::builder().build(); + // build with empty db + Evm::builder().with_empty_db().build(); + // build with_db + Evm::builder().with_db(EmptyDB::default()).build(); + // build with empty external + Evm::builder().with_empty_db().build(); + // build with some external + Evm::builder() + .with_empty_db() + .with_external_context(()) + .build(); + // build with spec + Evm::builder() + .with_empty_db() + .with_spec_id(SpecId::HOMESTEAD) + .build(); + + // with with Env change in multiple places + Evm::builder() + .with_empty_db() + .modify_tx_env(|tx| tx.gas_limit = 10) + .build(); + Evm::builder().modify_tx_env(|tx| tx.gas_limit = 10).build(); + Evm::builder() + .with_empty_db() + .modify_tx_env(|tx| tx.gas_limit = 10) + .build(); + Evm::builder() + .with_empty_db() + .modify_tx_env(|tx| tx.gas_limit = 10) + .build(); + + // with inspector handle + Evm::builder() + .with_empty_db() + .with_external_context(NoOpInspector) + .append_handler_register(inspector_handle_register) + .build(); + + // create the builder + let evm = Evm::builder() + .with_db(EmptyDB::default()) + .with_external_context(NoOpInspector) + .append_handler_register(inspector_handle_register) + // this would not compile + // .with_db(..) + .build(); + + let Context { external: _, .. } = evm.into_context(); + } + + #[test] + fn build_modify_build() { + // build evm + let evm = Evm::builder() + .with_empty_db() + .with_spec_id(SpecId::HOMESTEAD) + .build(); + + // modify evm + let evm = evm.modify().with_spec_id(SpecId::FRONTIER).build(); + let _ = evm + .modify() + .modify_tx_env(|tx| tx.chain_id = Some(2)) + .build(); + } + + #[test] + fn build_custom_precompile() { + struct CustomPrecompile; + + impl ContextStatefulPrecompile for CustomPrecompile { + fn call( + &self, + _input: &Bytes, + _gas_price: u64, + _context: &mut InnerEvmContext, + ) -> PrecompileResult { + Ok((10, Bytes::new())) + } + } + + let mut evm = Evm::builder() + .with_empty_db() + .with_spec_id(SpecId::HOMESTEAD) + .append_handler_register(|handler| { + let precompiles = handler.pre_execution.load_precompiles(); + handler.pre_execution.load_precompiles = Arc::new(move || { + let mut precompiles = precompiles.clone(); + precompiles.extend([( + Address::ZERO, + ContextPrecompile::ContextStateful(Arc::new(CustomPrecompile)), + )]); + precompiles + }); + }) + .build(); + + evm.transact().unwrap(); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/context.md b/docs/revm-python-spec/revm-verif/revm/revm/src/context.md new file mode 100644 index 00000000..40e4d75c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/context.md @@ -0,0 +1,102 @@ +# ๐Ÿฆ€ context.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/context.rs) + +```rust +mod context_precompiles; +pub(crate) mod evm_context; +mod inner_evm_context; + +pub use context_precompiles::{ + ContextPrecompile, ContextPrecompiles, ContextStatefulPrecompile, ContextStatefulPrecompileArc, + ContextStatefulPrecompileBox, ContextStatefulPrecompileMut, +}; +pub use evm_context::EvmContext; +pub use inner_evm_context::InnerEvmContext; + +use crate::{ + db::{Database, EmptyDB}, + primitives::HandlerCfg, +}; +use std::boxed::Box; + +/// Main Context structure that contains both EvmContext and External context. +pub struct Context { + /// Evm Context (internal context). + pub evm: EvmContext, + /// External contexts. + pub external: EXT, +} + +impl Clone for Context +where + DB::Error: Clone, +{ + fn clone(&self) -> Self { + Self { + evm: self.evm.clone(), + external: self.external.clone(), + } + } +} + +impl Default for Context<(), EmptyDB> { + fn default() -> Self { + Self::new_empty() + } +} + +impl Context<(), EmptyDB> { + /// Creates empty context. This is useful for testing. + pub fn new_empty() -> Context<(), EmptyDB> { + Context { + evm: EvmContext::new(EmptyDB::new()), + external: (), + } + } +} + +impl Context<(), DB> { + /// Creates new context with database. + pub fn new_with_db(db: DB) -> Context<(), DB> { + Context { + evm: EvmContext::new_with_env(db, Box::default()), + external: (), + } + } +} + +impl Context { + /// Creates new context with external and database. + pub fn new(evm: EvmContext, external: EXT) -> Context { + Context { evm, external } + } +} + +/// Context with handler configuration. +pub struct ContextWithHandlerCfg { + /// Context of execution. + pub context: Context, + /// Handler configuration. + pub cfg: HandlerCfg, +} + +impl ContextWithHandlerCfg { + /// Creates new context with handler configuration. + pub fn new(context: Context, cfg: HandlerCfg) -> Self { + Self { cfg, context } + } +} + +impl Clone for ContextWithHandlerCfg +where + DB::Error: Clone, +{ + fn clone(&self) -> Self { + Self { + context: self.context.clone(), + cfg: self.cfg, + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/context/context_precompiles.md b/docs/revm-python-spec/revm-verif/revm/revm/src/context/context_precompiles.md new file mode 100644 index 00000000..fa284a85 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/context/context_precompiles.md @@ -0,0 +1,159 @@ +# ๐Ÿฆ€ context_precompiles.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/context/context_precompiles.rs) + +```rust +use crate::{ + precompile::{Precompile, PrecompileResult}, + primitives::{db::Database, Address, Bytes, HashMap}, +}; +use core::ops::{Deref, DerefMut}; +use dyn_clone::DynClone; +use revm_precompile::Precompiles; +use std::{boxed::Box, sync::Arc}; + +use super::InnerEvmContext; + +/// Precompile and its handlers. +pub enum ContextPrecompile { + /// Ordinary precompiles + Ordinary(Precompile), + /// Stateful precompile that is Arc over [`ContextStatefulPrecompile`] trait. + /// It takes a reference to input, gas limit and Context. + ContextStateful(ContextStatefulPrecompileArc), + /// Mutable stateful precompile that is Box over [`ContextStatefulPrecompileMut`] trait. + /// It takes a reference to input, gas limit and context. + ContextStatefulMut(ContextStatefulPrecompileBox), +} + +impl Clone for ContextPrecompile { + fn clone(&self) -> Self { + match self { + Self::Ordinary(arg0) => Self::Ordinary(arg0.clone()), + Self::ContextStateful(arg0) => Self::ContextStateful(arg0.clone()), + Self::ContextStatefulMut(arg0) => Self::ContextStatefulMut(arg0.clone()), + } + } +} + +#[derive(Clone)] +pub struct ContextPrecompiles { + inner: HashMap>, +} + +impl ContextPrecompiles { + /// Returns precompiles addresses. + #[inline] + pub fn addresses(&self) -> impl Iterator { + self.inner.keys() + } + + /// Extends the precompiles with the given precompiles. + /// + /// Other precompiles with overwrite existing precompiles. + #[inline] + pub fn extend( + &mut self, + other: impl IntoIterator)>>, + ) { + self.inner.extend(other.into_iter().map(Into::into)); + } + + /// Call precompile and executes it. Returns the result of the precompile execution. + /// None if the precompile does not exist. + #[inline] + pub fn call( + &mut self, + addess: Address, + bytes: &Bytes, + gas_price: u64, + evmctx: &mut InnerEvmContext, + ) -> Option { + let precompile = self.inner.get_mut(&addess)?; + + match precompile { + ContextPrecompile::Ordinary(p) => Some(p.call(bytes, gas_price, &evmctx.env)), + ContextPrecompile::ContextStatefulMut(p) => Some(p.call_mut(bytes, gas_price, evmctx)), + ContextPrecompile::ContextStateful(p) => Some(p.call(bytes, gas_price, evmctx)), + } + } +} + +impl Default for ContextPrecompiles { + fn default() -> Self { + Self { + inner: Default::default(), + } + } +} + +impl Deref for ContextPrecompiles { + type Target = HashMap>; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for ContextPrecompiles { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +/// Context aware stateful precompile trait. It is used to create +/// a arc precompile in [`ContextPrecompile`]. +pub trait ContextStatefulPrecompile: Sync + Send { + fn call( + &self, + bytes: &Bytes, + gas_price: u64, + evmctx: &mut InnerEvmContext, + ) -> PrecompileResult; +} + +/// Context aware mutable stateful precompile trait. It is used to create +/// a boxed precompile in [`ContextPrecompile`]. +pub trait ContextStatefulPrecompileMut: DynClone + Send + Sync { + fn call_mut( + &mut self, + bytes: &Bytes, + gas_price: u64, + evmctx: &mut InnerEvmContext, + ) -> PrecompileResult; +} + +dyn_clone::clone_trait_object!( ContextStatefulPrecompileMut); + +/// Arc over context stateful precompile. +pub type ContextStatefulPrecompileArc = Arc>; + +/// Box over context mutable stateful precompile +pub type ContextStatefulPrecompileBox = Box>; + +impl From for ContextPrecompile { + fn from(p: Precompile) -> Self { + ContextPrecompile::Ordinary(p) + } +} + +impl From for ContextPrecompiles { + fn from(p: Precompiles) -> Self { + ContextPrecompiles { + inner: p.inner.into_iter().map(|(k, v)| (k, v.into())).collect(), + } + } +} + +impl From<&Precompiles> for ContextPrecompiles { + fn from(p: &Precompiles) -> Self { + ContextPrecompiles { + inner: p + .inner + .iter() + .map(|(&k, v)| (k, v.clone().into())) + .collect(), + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/context/evm_context.md b/docs/revm-python-spec/revm-verif/revm/revm/src/context/evm_context.md new file mode 100644 index 00000000..d7dea47a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/context/evm_context.md @@ -0,0 +1,406 @@ +# ๐Ÿฆ€ evm_context.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/context/evm_context.rs) + +```rust +use revm_interpreter::CallValue; + +use super::inner_evm_context::InnerEvmContext; +use crate::{ + db::Database, + interpreter::{ + return_ok, CallInputs, Contract, Gas, InstructionResult, Interpreter, InterpreterResult, + }, + primitives::{Address, Bytes, EVMError, Env, HashSet, U256}, + ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, +}; +use core::{ + fmt, + ops::{Deref, DerefMut}, +}; +use std::boxed::Box; + +/// EVM context that contains the inner EVM context and precompiles. +pub struct EvmContext { + /// Inner EVM context. + pub inner: InnerEvmContext, + /// Precompiles that are available for evm. + pub precompiles: ContextPrecompiles, +} + +impl Clone for EvmContext +where + DB::Error: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + precompiles: ContextPrecompiles::default(), + } + } +} + +impl fmt::Debug for EvmContext +where + DB: Database + fmt::Debug, + DB::Error: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EvmContext") + .field("inner", &self.inner) + .field("precompiles", &self.inner) + .finish_non_exhaustive() + } +} + +impl Deref for EvmContext { + type Target = InnerEvmContext; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for EvmContext { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +impl EvmContext { + /// Create new context with database. + pub fn new(db: DB) -> Self { + Self { + inner: InnerEvmContext::new(db), + precompiles: ContextPrecompiles::default(), + } + } + + /// Creates a new context with the given environment and database. + #[inline] + pub fn new_with_env(db: DB, env: Box) -> Self { + Self { + inner: InnerEvmContext::new_with_env(db, env), + precompiles: ContextPrecompiles::default(), + } + } + + /// Sets the database. + /// + /// Note that this will ignore the previous `error` if set. + #[inline] + pub fn with_db(self, db: ODB) -> EvmContext { + EvmContext { + inner: self.inner.with_db(db), + precompiles: ContextPrecompiles::default(), + } + } + + /// Sets precompiles + #[inline] + pub fn set_precompiles(&mut self, precompiles: ContextPrecompiles) { + // set warm loaded addresses. + self.journaled_state.warm_preloaded_addresses = + precompiles.addresses().copied().collect::>(); + self.precompiles = precompiles; + } + + /// Call precompile contract + #[inline] + fn call_precompile( + &mut self, + address: Address, + input_data: &Bytes, + gas: Gas, + ) -> Option { + let out = self + .precompiles + .call(address, input_data, gas.limit(), &mut self.inner)?; + + let mut result = InterpreterResult { + result: InstructionResult::Return, + gas, + output: Bytes::new(), + }; + + match out { + Ok((gas_used, data)) => { + if result.gas.record_cost(gas_used) { + result.result = InstructionResult::Return; + result.output = data; + } else { + result.result = InstructionResult::PrecompileOOG; + } + } + Err(e) => { + result.result = if e == crate::precompile::Error::OutOfGas { + InstructionResult::PrecompileOOG + } else { + InstructionResult::PrecompileError + }; + } + } + Some(result) + } + + /// Make call frame + #[inline] + pub fn make_call_frame( + &mut self, + inputs: &CallInputs, + ) -> Result> { + let gas = Gas::new(inputs.gas_limit); + + let return_result = |instruction_result: InstructionResult| { + Ok(FrameOrResult::new_call_result( + InterpreterResult { + result: instruction_result, + gas, + output: Bytes::new(), + }, + inputs.return_memory_offset.clone(), + )) + }; + + // Check depth + if self.journaled_state.depth() > CALL_STACK_LIMIT { + return return_result(InstructionResult::CallTooDeep); + } + + let (account, _) = self + .inner + .journaled_state + .load_code(inputs.bytecode_address, &mut self.inner.db)?; + let code_hash = account.info.code_hash(); + let bytecode = account.info.code.clone().unwrap_or_default(); + + // Create subroutine checkpoint + let checkpoint = self.journaled_state.checkpoint(); + + // Touch address. For "EIP-158 State Clear", this will erase empty accounts. + match inputs.value { + // if transfer value is zero, do the touch. + CallValue::Transfer(value) if value == U256::ZERO => { + self.load_account(inputs.target_address)?; + self.journaled_state.touch(&inputs.target_address); + } + CallValue::Transfer(value) => { + // Transfer value from caller to called account + if let Some(result) = self.inner.journaled_state.transfer( + &inputs.caller, + &inputs.target_address, + value, + &mut self.inner.db, + )? { + self.journaled_state.checkpoint_revert(checkpoint); + return return_result(result); + } + } + _ => {} + }; + + if let Some(result) = self.call_precompile(inputs.bytecode_address, &inputs.input, gas) { + if matches!(result.result, return_ok!()) { + self.journaled_state.checkpoint_commit(); + } else { + self.journaled_state.checkpoint_revert(checkpoint); + } + Ok(FrameOrResult::new_call_result( + result, + inputs.return_memory_offset.clone(), + )) + } else if !bytecode.is_empty() { + let contract = + Contract::new_with_context(inputs.input.clone(), bytecode, Some(code_hash), inputs); + // Create interpreter and executes call and push new CallStackFrame. + Ok(FrameOrResult::new_call_frame( + inputs.return_memory_offset.clone(), + checkpoint, + Interpreter::new(contract, gas.limit(), inputs.is_static), + )) + } else { + self.journaled_state.checkpoint_commit(); + return_result(InstructionResult::Stop) + } + } +} + +/// Test utilities for the [`EvmContext`]. +#[cfg(any(test, feature = "test-utils"))] +pub(crate) mod test_utils { + use super::*; + use crate::{ + db::{CacheDB, EmptyDB}, + journaled_state::JournaledState, + primitives::{address, SpecId, B256}, + }; + + /// Mock caller address. + pub const MOCK_CALLER: Address = address!("0000000000000000000000000000000000000000"); + + /// Creates `CallInputs` that calls a provided contract address from the mock caller. + pub fn create_mock_call_inputs(to: Address) -> CallInputs { + CallInputs { + input: Bytes::new(), + gas_limit: 0, + bytecode_address: to, + target_address: to, + caller: MOCK_CALLER, + value: CallValue::Transfer(U256::ZERO), + scheme: revm_interpreter::CallScheme::Call, + is_eof: false, + is_static: false, + return_memory_offset: 0..0, + } + } + + /// Creates an evm context with a cache db backend. + /// Additionally loads the mock caller account into the db, + /// and sets the balance to the provided U256 value. + pub fn create_cache_db_evm_context_with_balance( + env: Box, + mut db: CacheDB, + balance: U256, + ) -> EvmContext> { + db.insert_account_info( + test_utils::MOCK_CALLER, + crate::primitives::AccountInfo { + nonce: 0, + balance, + code_hash: B256::default(), + code: None, + }, + ); + create_cache_db_evm_context(env, db) + } + + /// Creates a cached db evm context. + pub fn create_cache_db_evm_context( + env: Box, + db: CacheDB, + ) -> EvmContext> { + EvmContext { + inner: InnerEvmContext { + env, + journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), + db, + error: Ok(()), + #[cfg(feature = "optimism")] + l1_block_info: None, + }, + precompiles: ContextPrecompiles::default(), + } + } + + /// Returns a new `EvmContext` with an empty journaled state. + pub fn create_empty_evm_context(env: Box, db: EmptyDB) -> EvmContext { + EvmContext { + inner: InnerEvmContext { + env, + journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), + db, + error: Ok(()), + #[cfg(feature = "optimism")] + l1_block_info: None, + }, + precompiles: ContextPrecompiles::default(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + db::{CacheDB, EmptyDB}, + primitives::{address, Bytecode}, + Frame, JournalEntry, + }; + use std::boxed::Box; + use test_utils::*; + + // Tests that the `EVMContext::make_call_frame` function returns an error if the + // call stack is too deep. + #[test] + fn test_make_call_frame_stack_too_deep() { + let env = Env::default(); + let db = EmptyDB::default(); + let mut context = test_utils::create_empty_evm_context(Box::new(env), db); + context.journaled_state.depth = CALL_STACK_LIMIT as usize + 1; + let contract = address!("dead10000000000000000000000000000001dead"); + let call_inputs = test_utils::create_mock_call_inputs(contract); + let res = context.make_call_frame(&call_inputs); + let Ok(FrameOrResult::Result(err)) = res else { + panic!("Expected FrameOrResult::Result"); + }; + assert_eq!( + err.interpreter_result().result, + InstructionResult::CallTooDeep + ); + } + + // Tests that the `EVMContext::make_call_frame` function returns an error if the + // transfer fails on the journaled state. It also verifies that the revert was + // checkpointed on the journaled state correctly. + #[test] + fn test_make_call_frame_transfer_revert() { + let env = Env::default(); + let db = EmptyDB::default(); + let mut evm_context = test_utils::create_empty_evm_context(Box::new(env), db); + let contract = address!("dead10000000000000000000000000000001dead"); + let mut call_inputs = test_utils::create_mock_call_inputs(contract); + call_inputs.value = CallValue::Transfer(U256::from(1)); + let res = evm_context.make_call_frame(&call_inputs); + let Ok(FrameOrResult::Result(result)) = res else { + panic!("Expected FrameOrResult::Result"); + }; + assert_eq!( + result.interpreter_result().result, + InstructionResult::OutOfFunds + ); + let checkpointed = vec![vec![JournalEntry::AccountLoaded { address: contract }]]; + assert_eq!(evm_context.journaled_state.journal, checkpointed); + assert_eq!(evm_context.journaled_state.depth, 0); + } + + #[test] + fn test_make_call_frame_missing_code_context() { + let env = Env::default(); + let cdb = CacheDB::new(EmptyDB::default()); + let bal = U256::from(3_000_000_000_u128); + let mut context = create_cache_db_evm_context_with_balance(Box::new(env), cdb, bal); + let contract = address!("dead10000000000000000000000000000001dead"); + let call_inputs = test_utils::create_mock_call_inputs(contract); + let res = context.make_call_frame(&call_inputs); + let Ok(FrameOrResult::Result(result)) = res else { + panic!("Expected FrameOrResult::Result"); + }; + assert_eq!(result.interpreter_result().result, InstructionResult::Stop); + } + + #[test] + fn test_make_call_frame_succeeds() { + let env = Env::default(); + let mut cdb = CacheDB::new(EmptyDB::default()); + let bal = U256::from(3_000_000_000_u128); + let by = Bytecode::new_raw(Bytes::from(vec![0x60, 0x00, 0x60, 0x00])); + let contract = address!("dead10000000000000000000000000000001dead"); + cdb.insert_account_info( + contract, + crate::primitives::AccountInfo { + nonce: 0, + balance: bal, + code_hash: by.clone().hash_slow(), + code: Some(by), + }, + ); + let mut evm_context = create_cache_db_evm_context_with_balance(Box::new(env), cdb, bal); + let call_inputs = test_utils::create_mock_call_inputs(contract); + let res = evm_context.make_call_frame(&call_inputs); + let Ok(FrameOrResult::Frame(Frame::Call(call_frame))) = res else { + panic!("Expected FrameOrResult::Frame(Frame::Call(..))"); + }; + assert_eq!(call_frame.return_memory_range, 0..0,); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/context/inner_evm_context.md b/docs/revm-python-spec/revm-verif/revm/revm/src/context/inner_evm_context.md new file mode 100644 index 00000000..6f632024 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/context/inner_evm_context.md @@ -0,0 +1,512 @@ +# ๐Ÿฆ€ inner_evm_context.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/context/inner_evm_context.rs) + +```rust +use crate::{ + db::Database, + interpreter::{ + analysis::to_analysed, gas, return_ok, Contract, CreateInputs, EOFCreateInput, Gas, + InstructionResult, Interpreter, InterpreterResult, LoadAccountResult, SStoreResult, + SelfDestructResult, MAX_CODE_SIZE, + }, + journaled_state::JournaledState, + primitives::{ + keccak256, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, EVMError, Env, + Eof, HashSet, Spec, + SpecId::{self, *}, + B256, U256, + }, + FrameOrResult, JournalCheckpoint, CALL_STACK_LIMIT, +}; +use std::boxed::Box; + +/// EVM contexts contains data that EVM needs for execution. +#[derive(Debug)] +pub struct InnerEvmContext { + /// EVM Environment contains all the information about config, block and transaction that + /// evm needs. + pub env: Box, + /// EVM State with journaling support. + pub journaled_state: JournaledState, + /// Database to load data from. + pub db: DB, + /// Error that happened during execution. + pub error: Result<(), EVMError>, + /// Used as temporary value holder to store L1 block info. + #[cfg(feature = "optimism")] + pub l1_block_info: Option, +} + +impl Clone for InnerEvmContext +where + DB::Error: Clone, +{ + fn clone(&self) -> Self { + Self { + env: self.env.clone(), + journaled_state: self.journaled_state.clone(), + db: self.db.clone(), + error: self.error.clone(), + #[cfg(feature = "optimism")] + l1_block_info: self.l1_block_info.clone(), + } + } +} + +impl InnerEvmContext { + pub fn new(db: DB) -> Self { + Self { + env: Box::default(), + journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), + db, + error: Ok(()), + #[cfg(feature = "optimism")] + l1_block_info: None, + } + } + + /// Creates a new context with the given environment and database. + #[inline] + pub fn new_with_env(db: DB, env: Box) -> Self { + Self { + env, + journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), + db, + error: Ok(()), + #[cfg(feature = "optimism")] + l1_block_info: None, + } + } + + /// Sets the database. + /// + /// Note that this will ignore the previous `error` if set. + #[inline] + pub fn with_db(self, db: ODB) -> InnerEvmContext { + InnerEvmContext { + env: self.env, + journaled_state: self.journaled_state, + db, + error: Ok(()), + #[cfg(feature = "optimism")] + l1_block_info: self.l1_block_info, + } + } + + /// Returns the configured EVM spec ID. + #[inline] + pub const fn spec_id(&self) -> SpecId { + self.journaled_state.spec + } + + /// Load access list for berlin hard fork. + /// + /// Loading of accounts/storages is needed to make them warm. + #[inline] + pub fn load_access_list(&mut self) -> Result<(), EVMError> { + for (address, slots) in self.env.tx.access_list.iter() { + self.journaled_state + .initial_account_load(*address, slots, &mut self.db)?; + } + Ok(()) + } + + /// Return environment. + #[inline] + pub fn env(&mut self) -> &mut Env { + &mut self.env + } + + /// Returns the error by replacing it with `Ok(())`, if any. + pub fn take_error(&mut self) -> Result<(), EVMError> { + core::mem::replace(&mut self.error, Ok(())) + } + + /// Fetch block hash from database. + #[inline] + pub fn block_hash(&mut self, number: U256) -> Result> { + self.db.block_hash(number).map_err(EVMError::Database) + } + + /// Mark account as touched as only touched accounts will be added to state. + #[inline] + pub fn touch(&mut self, address: &Address) { + self.journaled_state.touch(address); + } + + /// Loads an account into memory. Returns `true` if it is cold accessed. + #[inline] + pub fn load_account( + &mut self, + address: Address, + ) -> Result<(&mut Account, bool), EVMError> { + self.journaled_state.load_account(address, &mut self.db) + } + + /// Load account from database to JournaledState. + /// + /// Return boolean pair where first is `is_cold` second bool `exists`. + #[inline] + pub fn load_account_exist( + &mut self, + address: Address, + ) -> Result> { + self.journaled_state + .load_account_exist(address, &mut self.db) + } + + /// Return account balance and is_cold flag. + #[inline] + pub fn balance(&mut self, address: Address) -> Result<(U256, bool), EVMError> { + self.journaled_state + .load_account(address, &mut self.db) + .map(|(acc, is_cold)| (acc.info.balance, is_cold)) + } + + /// Return account code and if address is cold loaded. + #[inline] + pub fn code(&mut self, address: Address) -> Result<(Bytecode, bool), EVMError> { + self.journaled_state + .load_code(address, &mut self.db) + .map(|(a, is_cold)| (a.info.code.clone().unwrap(), is_cold)) + } + + /// Get code hash of address. + #[inline] + pub fn code_hash(&mut self, address: Address) -> Result<(B256, bool), EVMError> { + let (acc, is_cold) = self.journaled_state.load_code(address, &mut self.db)?; + if acc.is_empty() { + return Ok((B256::ZERO, is_cold)); + } + Ok((acc.info.code_hash, is_cold)) + } + + /// Load storage slot, if storage is not present inside the account then it will be loaded from database. + #[inline] + pub fn sload( + &mut self, + address: Address, + index: U256, + ) -> Result<(U256, bool), EVMError> { + // account is always warm. reference on that statement https://eips.ethereum.org/EIPS/eip-2929 see `Note 2:` + self.journaled_state.sload(address, index, &mut self.db) + } + + /// Storage change of storage slot, before storing `sload` will be called for that slot. + #[inline] + pub fn sstore( + &mut self, + address: Address, + index: U256, + value: U256, + ) -> Result> { + self.journaled_state + .sstore(address, index, value, &mut self.db) + } + + /// Returns transient storage value. + #[inline] + pub fn tload(&mut self, address: Address, index: U256) -> U256 { + self.journaled_state.tload(address, index) + } + + /// Stores transient storage value. + #[inline] + pub fn tstore(&mut self, address: Address, index: U256, value: U256) { + self.journaled_state.tstore(address, index, value) + } + + /// Selfdestructs the account. + #[inline] + pub fn selfdestruct( + &mut self, + address: Address, + target: Address, + ) -> Result> { + self.journaled_state + .selfdestruct(address, target, &mut self.db) + } + + /// Make create frame. + #[inline] + pub fn make_eofcreate_frame( + &mut self, + spec_id: SpecId, + inputs: &EOFCreateInput, + ) -> Result> { + let return_error = |e| { + Ok(FrameOrResult::new_eofcreate_result( + InterpreterResult { + result: e, + gas: Gas::new(inputs.gas_limit), + output: Bytes::new(), + }, + inputs.created_address, + inputs.return_memory_range.clone(), + )) + }; + + // Check depth + if self.journaled_state.depth() > CALL_STACK_LIMIT { + return return_error(InstructionResult::CallTooDeep); + } + + // Fetch balance of caller. + let (caller_balance, _) = self.balance(inputs.caller)?; + + // Check if caller has enough balance to send to the created contract. + if caller_balance < inputs.value { + return return_error(InstructionResult::OutOfFunds); + } + + // Increase nonce of caller and check if it overflows + if self.journaled_state.inc_nonce(inputs.caller).is_none() { + // can't happen on mainnet. + return return_error(InstructionResult::Return); + } + + // Load account so it needs to be marked as warm for access list. + self.journaled_state + .load_account(inputs.created_address, &mut self.db)?; + + // create account, transfer funds and make the journal checkpoint. + let checkpoint = match self.journaled_state.create_account_checkpoint( + inputs.caller, + inputs.created_address, + inputs.value, + spec_id, + ) { + Ok(checkpoint) => checkpoint, + Err(e) => { + return return_error(e); + } + }; + + let contract = Contract::new( + Bytes::new(), + // fine to clone as it is Bytes. + Bytecode::Eof(inputs.eof_init_code.clone()), + None, + inputs.created_address, + inputs.caller, + inputs.value, + ); + + let mut interpreter = Interpreter::new(contract, inputs.gas_limit, false); + // EOF init will enable RETURNCONTRACT opcode. + interpreter.set_is_eof_init(); + + Ok(FrameOrResult::new_eofcreate_frame( + inputs.created_address, + inputs.return_memory_range.clone(), + checkpoint, + interpreter, + )) + } + + /// If error is present revert changes, otherwise save EOF bytecode. + pub fn eofcreate_return( + &mut self, + interpreter_result: &mut InterpreterResult, + address: Address, + journal_checkpoint: JournalCheckpoint, + ) { + // Note we still execute RETURN opcode and return the bytes. + // In EOF those opcodes should abort execution. + // + // In RETURN gas is still protecting us from ddos and in oog, + // behaviour will be same as if it failed on return. + // + // Bytes of RETURN will drained in `insert_eofcreate_outcome`. + if interpreter_result.result != InstructionResult::ReturnContract { + self.journaled_state.checkpoint_revert(journal_checkpoint); + return; + } + + // commit changes reduces depth by -1. + self.journaled_state.checkpoint_commit(); + + // decode bytecode has a performance hit, but it has reasonable restrains. + let bytecode = + Eof::decode(interpreter_result.output.clone()).expect("Eof is already verified"); + + // eof bytecode is going to be hashed. + self.journaled_state + .set_code(address, Bytecode::Eof(bytecode)); + } + + /// Make create frame. + #[inline] + pub fn make_create_frame( + &mut self, + spec_id: SpecId, + inputs: &CreateInputs, + ) -> Result> { + // Prepare crate. + let gas = Gas::new(inputs.gas_limit); + + let return_error = |e| { + Ok(FrameOrResult::new_create_result( + InterpreterResult { + result: e, + gas, + output: Bytes::new(), + }, + None, + )) + }; + + // Check depth + if self.journaled_state.depth() > CALL_STACK_LIMIT { + return return_error(InstructionResult::CallTooDeep); + } + + // Fetch balance of caller. + let (caller_balance, _) = self.balance(inputs.caller)?; + + // Check if caller has enough balance to send to the created contract. + if caller_balance < inputs.value { + return return_error(InstructionResult::OutOfFunds); + } + + // Increase nonce of caller and check if it overflows + let old_nonce; + if let Some(nonce) = self.journaled_state.inc_nonce(inputs.caller) { + old_nonce = nonce - 1; + } else { + return return_error(InstructionResult::Return); + } + + // Create address + let mut init_code_hash = B256::ZERO; + let created_address = match inputs.scheme { + CreateScheme::Create => inputs.caller.create(old_nonce), + CreateScheme::Create2 { salt } => { + init_code_hash = keccak256(&inputs.init_code); + inputs.caller.create2(salt.to_be_bytes(), init_code_hash) + } + }; + + // Load account so it needs to be marked as warm for access list. + self.journaled_state + .load_account(created_address, &mut self.db)?; + + // create account, transfer funds and make the journal checkpoint. + let checkpoint = match self.journaled_state.create_account_checkpoint( + inputs.caller, + created_address, + inputs.value, + spec_id, + ) { + Ok(checkpoint) => checkpoint, + Err(e) => { + return return_error(e); + } + }; + + let bytecode = Bytecode::new_raw(inputs.init_code.clone()); + + let contract = Contract::new( + Bytes::new(), + bytecode, + Some(init_code_hash), + created_address, + inputs.caller, + inputs.value, + ); + + Ok(FrameOrResult::new_create_frame( + created_address, + checkpoint, + Interpreter::new(contract, gas.limit(), false), + )) + } + + /// Handles call return. + #[inline] + pub fn call_return( + &mut self, + interpreter_result: &InterpreterResult, + journal_checkpoint: JournalCheckpoint, + ) { + // revert changes or not. + if matches!(interpreter_result.result, return_ok!()) { + self.journaled_state.checkpoint_commit(); + } else { + self.journaled_state.checkpoint_revert(journal_checkpoint); + } + } + + /// Handles create return. + #[inline] + pub fn create_return( + &mut self, + interpreter_result: &mut InterpreterResult, + address: Address, + journal_checkpoint: JournalCheckpoint, + ) { + // if return is not ok revert and return. + if !matches!(interpreter_result.result, return_ok!()) { + self.journaled_state.checkpoint_revert(journal_checkpoint); + return; + } + // Host error if present on execution + // if ok, check contract creation limit and calculate gas deduction on output len. + // + // EIP-3541: Reject new contract code starting with the 0xEF byte + if SPEC::enabled(LONDON) + && !interpreter_result.output.is_empty() + && interpreter_result.output.first() == Some(&0xEF) + { + self.journaled_state.checkpoint_revert(journal_checkpoint); + interpreter_result.result = InstructionResult::CreateContractStartingWithEF; + return; + } + + // EIP-170: Contract code size limit + // By default limit is 0x6000 (~25kb) + if SPEC::enabled(SPURIOUS_DRAGON) + && interpreter_result.output.len() + > self + .env + .cfg + .limit_contract_code_size + .unwrap_or(MAX_CODE_SIZE) + { + self.journaled_state.checkpoint_revert(journal_checkpoint); + interpreter_result.result = InstructionResult::CreateContractSizeLimit; + return; + } + let gas_for_code = interpreter_result.output.len() as u64 * gas::CODEDEPOSIT; + if !interpreter_result.gas.record_cost(gas_for_code) { + // record code deposit gas cost and check if we are out of gas. + // EIP-2 point 3: If contract creation does not have enough gas to pay for the + // final gas fee for adding the contract code to the state, the contract + // creation fails (i.e. goes out-of-gas) rather than leaving an empty contract. + if SPEC::enabled(HOMESTEAD) { + self.journaled_state.checkpoint_revert(journal_checkpoint); + interpreter_result.result = InstructionResult::OutOfGas; + return; + } else { + interpreter_result.output = Bytes::new(); + } + } + // if we have enough gas we can commit changes. + self.journaled_state.checkpoint_commit(); + + // Do analysis of bytecode straight away. + let bytecode = match self.env.cfg.perf_analyse_created_bytecodes { + AnalysisKind::Raw => Bytecode::new_raw(interpreter_result.output.clone()), + AnalysisKind::Analyse => { + to_analysed(Bytecode::new_raw(interpreter_result.output.clone())) + } + }; + + // set code + self.journaled_state.set_code(address, bytecode); + + interpreter_result.result = InstructionResult::Return; + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db.md new file mode 100644 index 00000000..52095e62 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db.md @@ -0,0 +1,28 @@ +# ๐Ÿฆ€ db.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db.rs) + +```rust +//! [Database] implementations. + +#[cfg(feature = "alloydb")] +pub mod alloydb; +pub mod emptydb; +#[cfg(feature = "ethersdb")] +pub mod ethersdb; +pub mod in_memory_db; +pub mod states; + +pub use crate::primitives::db::*; +#[cfg(feature = "alloydb")] +pub use alloydb::AlloyDB; +pub use emptydb::{EmptyDB, EmptyDBTyped}; +#[cfg(feature = "ethersdb")] +pub use ethersdb::EthersDB; +pub use in_memory_db::*; +pub use states::{ + AccountRevert, AccountStatus, BundleAccount, BundleState, CacheState, DBBox, + OriginalValuesKnown, PlainAccount, RevertToSlot, State, StateBuilder, StateDBBox, + StorageWithOriginalValues, TransitionAccount, TransitionState, +}; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/alloydb.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/alloydb.md new file mode 100644 index 00000000..123619d3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/alloydb.md @@ -0,0 +1,186 @@ +# ๐Ÿฆ€ alloydb.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/alloydb.rs) + +```rust +use crate::{ + db::{Database, DatabaseRef}, + primitives::{AccountInfo, Address, Bytecode, B256, KECCAK_EMPTY, U256}, +}; +use alloy_provider::{Network, Provider}; +use alloy_rpc_types::BlockId; +use alloy_transport::{Transport, TransportError}; +use tokio::runtime::{Builder, Handle}; + +/// An alloy-powered REVM [Database]. +/// +/// When accessing the database, it'll use the given provider to fetch the corresponding account's data. +#[derive(Debug, Clone)] +pub struct AlloyDB> { + /// The provider to fetch the data from. + provider: P, + /// The block number on which the queries will be based on. + block_number: Option, + _marker: std::marker::PhantomData (T, N)>, +} + +impl> AlloyDB { + /// Create a new AlloyDB instance, with a [Provider] and a block (Use None for latest). + pub fn new(provider: P, block_number: Option) -> Self { + Self { + provider, + block_number, + _marker: std::marker::PhantomData, + } + } + + /// Internal utility function that allows us to block on a future regardless of the runtime flavor. + #[inline] + fn block_on(f: F) -> F::Output + where + F: std::future::Future + Send, + F::Output: Send, + { + match Handle::try_current() { + Ok(handle) => match handle.runtime_flavor() { + // This is essentially equal to tokio::task::spawn_blocking because tokio doesn't + // allow the current_thread runtime to block_in_place. + // See for more info. + tokio::runtime::RuntimeFlavor::CurrentThread => std::thread::scope(move |s| { + s.spawn(move || { + Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(f) + }) + .join() + .unwrap() + }), + _ => tokio::task::block_in_place(move || handle.block_on(f)), + }, + Err(_) => Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(f), + } + } + + /// Set the block number on which the queries will be based on. + pub fn set_block_number(&mut self, block_number: Option) { + self.block_number = block_number; + } +} + +impl> DatabaseRef for AlloyDB { + type Error = TransportError; + + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + let f = async { + let nonce = self + .provider + .get_transaction_count(address, self.block_number); + let balance = self.provider.get_balance(address, self.block_number); + let code = self + .provider + .get_code_at(address, self.block_number.unwrap_or_default()); + tokio::join!(nonce, balance, code) + }; + + let (nonce, balance, code) = Self::block_on(f); + + let balance = balance?; + let code = Bytecode::new_raw(code?.0.into()); + let code_hash = code.hash_slow(); + let nonce = nonce?; + + Ok(Some(AccountInfo::new( + balance, + nonce.to::(), + code_hash, + code, + ))) + } + + fn block_hash_ref(&self, number: U256) -> Result { + // Saturate usize + if number > U256::from(u64::MAX) { + return Ok(KECCAK_EMPTY); + } + + let block = Self::block_on( + self.provider + // SAFETY: We know number <= u64::MAX, so we can safely convert it to u64 + .get_block_by_number(number.to::().into(), false), + )?; + // SAFETY: If the number is given, the block is supposed to be finalized, so unwrapping is safe. + Ok(B256::new(*block.unwrap().header.hash.unwrap())) + } + + fn code_by_hash_ref(&self, _code_hash: B256) -> Result { + panic!("This should not be called, as the code is already loaded"); + // This is not needed, as the code is already loaded with basic_ref + } + + fn storage_ref(&self, address: Address, index: U256) -> Result { + let slot_val = Self::block_on(self.provider.get_storage_at( + address, + index, + self.block_number, + ))?; + Ok(slot_val) + } +} + +impl> Database for AlloyDB { + type Error = TransportError; + + #[inline] + fn basic(&mut self, address: Address) -> Result, Self::Error> { + ::basic_ref(self, address) + } + + #[inline] + fn code_by_hash(&mut self, code_hash: B256) -> Result { + ::code_by_hash_ref(self, code_hash) + } + + #[inline] + fn storage(&mut self, address: Address, index: U256) -> Result { + ::storage_ref(self, address, index) + } + + #[inline] + fn block_hash(&mut self, number: U256) -> Result { + ::block_hash_ref(self, number) + } +} + +#[cfg(test)] +mod tests { + use alloy_provider::ProviderBuilder; + + use super::*; + + #[test] + fn can_get_basic() { + let client = ProviderBuilder::new() + .on_reqwest_http( + "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27" + .parse() + .unwrap(), + ) + .unwrap(); + let alloydb = AlloyDB::new(client, Some(BlockId::from(16148323))); + + // ETH/USDT pair on Uniswap V2 + let address: Address = "0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852" + .parse() + .unwrap(); + + let acc_info = alloydb.basic_ref(address).unwrap().unwrap(); + assert!(acc_info.exists()); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/emptydb.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/emptydb.md new file mode 100644 index 00000000..ec7213bd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/emptydb.md @@ -0,0 +1,145 @@ +# ๐Ÿฆ€ emptydb.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/emptydb.rs) + +```rust +use core::{convert::Infallible, fmt, marker::PhantomData}; +use revm_interpreter::primitives::{ + db::{Database, DatabaseRef}, + keccak256, AccountInfo, Address, Bytecode, B256, U256, +}; +use std::string::ToString; + +/// An empty database that always returns default values when queried. +pub type EmptyDB = EmptyDBTyped; + +/// An empty database that always returns default values when queried. +/// +/// This is generic over a type which is used as the database error type. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct EmptyDBTyped { + _phantom: PhantomData, +} + +// Don't derive traits, because the type parameter is unused. +impl Clone for EmptyDBTyped { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for EmptyDBTyped {} + +impl Default for EmptyDBTyped { + fn default() -> Self { + Self::new() + } +} + +impl fmt::Debug for EmptyDBTyped { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EmptyDB").finish_non_exhaustive() + } +} + +impl PartialEq for EmptyDBTyped { + fn eq(&self, _: &Self) -> bool { + true + } +} + +impl Eq for EmptyDBTyped {} + +impl EmptyDBTyped { + pub fn new() -> Self { + Self { + _phantom: PhantomData, + } + } + + #[doc(hidden)] + #[deprecated = "use `new` instead"] + pub fn new_keccak_block_hash() -> Self { + Self::new() + } +} + +impl Database for EmptyDBTyped { + type Error = E; + + #[inline] + fn basic(&mut self, address: Address) -> Result, Self::Error> { + ::basic_ref(self, address) + } + + #[inline] + fn code_by_hash(&mut self, code_hash: B256) -> Result { + ::code_by_hash_ref(self, code_hash) + } + + #[inline] + fn storage(&mut self, address: Address, index: U256) -> Result { + ::storage_ref(self, address, index) + } + + #[inline] + fn block_hash(&mut self, number: U256) -> Result { + ::block_hash_ref(self, number) + } +} + +impl DatabaseRef for EmptyDBTyped { + type Error = E; + + #[inline] + fn basic_ref(&self, _address: Address) -> Result, Self::Error> { + Ok(None) + } + + #[inline] + fn code_by_hash_ref(&self, _code_hash: B256) -> Result { + Ok(Bytecode::default()) + } + + #[inline] + fn storage_ref(&self, _address: Address, _index: U256) -> Result { + Ok(U256::default()) + } + + #[inline] + fn block_hash_ref(&self, number: U256) -> Result { + Ok(keccak256(number.to_string().as_bytes())) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::primitives::b256; + + #[test] + fn conform_block_hash_calculation() { + let db = EmptyDB::new(); + assert_eq!( + db.block_hash_ref(U256::from(0)), + Ok(b256!( + "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d" + )) + ); + + assert_eq!( + db.block_hash_ref(U256::from(1)), + Ok(b256!( + "c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6" + )) + ); + + assert_eq!( + db.block_hash_ref(U256::from(100)), + Ok(b256!( + "8c18210df0d9514f2d2e5d8ca7c100978219ee80d3968ad850ab5ead208287b3" + )) + ); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/ethersdb.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/ethersdb.md new file mode 100644 index 00000000..9abda030 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/ethersdb.md @@ -0,0 +1,181 @@ +# ๐Ÿฆ€ ethersdb.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/ethersdb.rs) + +```rust +use std::sync::Arc; + +use ethers_core::types::{Block, BlockId, TxHash, H160 as eH160, H256, U64 as eU64}; +use ethers_providers::Middleware; +use tokio::runtime::{Builder, Handle, RuntimeFlavor}; + +use crate::primitives::{AccountInfo, Address, Bytecode, B256, KECCAK_EMPTY, U256}; +use crate::{Database, DatabaseRef}; + +#[derive(Debug, Clone)] +pub struct EthersDB { + client: Arc, + block_number: Option, +} + +impl EthersDB { + /// create ethers db connector inputs are url and block on what we are basing our database (None for latest) + pub fn new(client: Arc, block_number: Option) -> Option { + let block_number: Option = if block_number.is_some() { + block_number + } else { + Some(BlockId::from( + Self::block_on(client.get_block_number()).ok()?, + )) + }; + + Some(Self { + client, + block_number, + }) + } + + /// internal utility function to call tokio feature and wait for output + #[inline] + fn block_on(f: F) -> F::Output + where + F: core::future::Future + Send, + F::Output: Send, + { + match Handle::try_current() { + Ok(handle) => match handle.runtime_flavor() { + // This essentially equals to tokio::task::spawn_blocking because tokio doesn't + // allow current_thread runtime to block_in_place + RuntimeFlavor::CurrentThread => std::thread::scope(move |s| { + s.spawn(move || { + Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(f) + }) + .join() + .unwrap() + }), + _ => tokio::task::block_in_place(move || handle.block_on(f)), + }, + Err(_) => Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(f), + } + } + + /// set block number on which upcoming queries will be based + #[inline] + pub fn set_block_number(&mut self, block_number: BlockId) { + self.block_number = Some(block_number); + } +} + +impl DatabaseRef for EthersDB { + type Error = M::Error; + + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + let add = eH160::from(address.0 .0); + + let f = async { + let nonce = self.client.get_transaction_count(add, self.block_number); + let balance = self.client.get_balance(add, self.block_number); + let code = self.client.get_code(add, self.block_number); + tokio::join!(nonce, balance, code) + }; + let (nonce, balance, code) = Self::block_on(f); + + let balance = U256::from_limbs(balance?.0); + let nonce = nonce?.as_u64(); + let bytecode = Bytecode::new_raw(code?.0.into()); + let code_hash = bytecode.hash_slow(); + Ok(Some(AccountInfo::new(balance, nonce, code_hash, bytecode))) + } + + fn code_by_hash_ref(&self, _code_hash: B256) -> Result { + panic!("Should not be called. Code is already loaded"); + // not needed because we already load code with basic info + } + + fn storage_ref(&self, address: Address, index: U256) -> Result { + let add = eH160::from(address.0 .0); + let index = H256::from(index.to_be_bytes()); + let slot_value: H256 = + Self::block_on(self.client.get_storage_at(add, index, self.block_number))?; + Ok(U256::from_be_bytes(slot_value.to_fixed_bytes())) + } + + fn block_hash_ref(&self, number: U256) -> Result { + // saturate usize + if number > U256::from(u64::MAX) { + return Ok(KECCAK_EMPTY); + } + // We know number <= u64::MAX so unwrap is safe + let number = eU64::from(u64::try_from(number).unwrap()); + let block: Option> = + Self::block_on(self.client.get_block(BlockId::from(number)))?; + // If number is given, the block is supposed to be finalized so unwrap is safe too. + Ok(B256::new(block.unwrap().hash.unwrap().0)) + } +} + +impl Database for EthersDB { + type Error = M::Error; + + #[inline] + fn basic(&mut self, address: Address) -> Result, Self::Error> { + ::basic_ref(self, address) + } + + #[inline] + fn code_by_hash(&mut self, code_hash: B256) -> Result { + ::code_by_hash_ref(self, code_hash) + } + + #[inline] + fn storage(&mut self, address: Address, index: U256) -> Result { + ::storage_ref(self, address, index) + } + + #[inline] + fn block_hash(&mut self, number: U256) -> Result { + ::block_hash_ref(self, number) + } +} + +// Run tests with `cargo test -- --nocapture` to see print statements +#[cfg(test)] +mod tests { + use super::*; + use ethers_providers::{Http, Provider}; + + //#[test] + fn _can_get_basic() { + let client = Provider::::try_from( + "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27", + ) + .unwrap(); + let client = Arc::new(client); + + let ethersdb = EthersDB::new( + Arc::clone(&client), // public infura mainnet + Some(BlockId::from(16148323)), + ) + .unwrap(); + + // ETH/USDT pair on Uniswap V2 + let address = "0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852" + .parse::() + .unwrap(); + let address = address.as_fixed_bytes().into(); + + let acc_info = ethersdb.basic_ref(address).unwrap().unwrap(); + + // check if not empty + assert!(acc_info.exists()); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/in_memory_db.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/in_memory_db.md new file mode 100644 index 00000000..cf8453b1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/in_memory_db.md @@ -0,0 +1,497 @@ +# ๐Ÿฆ€ in_memory_db.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/in_memory_db.rs) + +```rust +use super::{DatabaseCommit, DatabaseRef, EmptyDB}; +use crate::primitives::{ + hash_map::Entry, Account, AccountInfo, Address, Bytecode, HashMap, Log, B256, KECCAK_EMPTY, + U256, +}; +use crate::Database; +use core::convert::Infallible; +use std::vec::Vec; + +/// A [Database] implementation that stores all state changes in memory. +pub type InMemoryDB = CacheDB; + +/// A [Database] implementation that stores all state changes in memory. +/// +/// This implementation wraps a [DatabaseRef] that is used to load data ([AccountInfo]). +/// +/// Accounts and code are stored in two separate maps, the `accounts` map maps addresses to [DbAccount], +/// whereas contracts are identified by their code hash, and are stored in the `contracts` map. +/// The [DbAccount] holds the code hash of the contract, which is used to look up the contract in the `contracts` map. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CacheDB { + /// Account info where None means it is not existing. Not existing state is needed for Pre TANGERINE forks. + /// `code` is always `None`, and bytecode can be found in `contracts`. + pub accounts: HashMap, + /// Tracks all contracts by their code hash. + pub contracts: HashMap, + /// All logs that were committed via [DatabaseCommit::commit]. + pub logs: Vec, + /// All cached block hashes from the [DatabaseRef]. + pub block_hashes: HashMap, + /// The underlying database ([DatabaseRef]) that is used to load data. + /// + /// Note: this is read-only, data is never written to this database. + pub db: ExtDB, +} + +impl Default for CacheDB { + fn default() -> Self { + Self::new(ExtDB::default()) + } +} + +impl CacheDB { + pub fn new(db: ExtDB) -> Self { + let mut contracts = HashMap::new(); + contracts.insert(KECCAK_EMPTY, Bytecode::default()); + contracts.insert(B256::ZERO, Bytecode::default()); + Self { + accounts: HashMap::new(), + contracts, + logs: Vec::default(), + block_hashes: HashMap::new(), + db, + } + } + + /// Inserts the account's code into the cache. + /// + /// Accounts objects and code are stored separately in the cache, this will take the code from the account and instead map it to the code hash. + /// + /// Note: This will not insert into the underlying external database. + pub fn insert_contract(&mut self, account: &mut AccountInfo) { + if let Some(code) = &account.code { + if !code.is_empty() { + if account.code_hash == KECCAK_EMPTY { + account.code_hash = code.hash_slow(); + } + self.contracts + .entry(account.code_hash) + .or_insert_with(|| code.clone()); + } + } + if account.code_hash == B256::ZERO { + account.code_hash = KECCAK_EMPTY; + } + } + + /// Insert account info but not override storage + pub fn insert_account_info(&mut self, address: Address, mut info: AccountInfo) { + self.insert_contract(&mut info); + self.accounts.entry(address).or_default().info = info; + } +} + +impl CacheDB { + /// Returns the account for the given address. + /// + /// If the account was not found in the cache, it will be loaded from the underlying database. + pub fn load_account(&mut self, address: Address) -> Result<&mut DbAccount, ExtDB::Error> { + let db = &self.db; + match self.accounts.entry(address) { + Entry::Occupied(entry) => Ok(entry.into_mut()), + Entry::Vacant(entry) => Ok(entry.insert( + db.basic_ref(address)? + .map(|info| DbAccount { + info, + ..Default::default() + }) + .unwrap_or_else(DbAccount::new_not_existing), + )), + } + } + + /// insert account storage without overriding account info + pub fn insert_account_storage( + &mut self, + address: Address, + slot: U256, + value: U256, + ) -> Result<(), ExtDB::Error> { + let account = self.load_account(address)?; + account.storage.insert(slot, value); + Ok(()) + } + + /// replace account storage without overriding account info + pub fn replace_account_storage( + &mut self, + address: Address, + storage: HashMap, + ) -> Result<(), ExtDB::Error> { + let account = self.load_account(address)?; + account.account_state = AccountState::StorageCleared; + account.storage = storage.into_iter().collect(); + Ok(()) + } +} + +impl DatabaseCommit for CacheDB { + fn commit(&mut self, changes: HashMap) { + for (address, mut account) in changes { + if !account.is_touched() { + continue; + } + if account.is_selfdestructed() { + let db_account = self.accounts.entry(address).or_default(); + db_account.storage.clear(); + db_account.account_state = AccountState::NotExisting; + db_account.info = AccountInfo::default(); + continue; + } + let is_newly_created = account.is_created(); + self.insert_contract(&mut account.info); + + let db_account = self.accounts.entry(address).or_default(); + db_account.info = account.info; + + db_account.account_state = if is_newly_created { + db_account.storage.clear(); + AccountState::StorageCleared + } else if db_account.account_state.is_storage_cleared() { + // Preserve old account state if it already exists + AccountState::StorageCleared + } else { + AccountState::Touched + }; + db_account.storage.extend( + account + .storage + .into_iter() + .map(|(key, value)| (key, value.present_value())), + ); + } + } +} + +impl Database for CacheDB { + type Error = ExtDB::Error; + + fn basic(&mut self, address: Address) -> Result, Self::Error> { + let basic = match self.accounts.entry(address) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert( + self.db + .basic_ref(address)? + .map(|info| DbAccount { + info, + ..Default::default() + }) + .unwrap_or_else(DbAccount::new_not_existing), + ), + }; + Ok(basic.info()) + } + + fn code_by_hash(&mut self, code_hash: B256) -> Result { + match self.contracts.entry(code_hash) { + Entry::Occupied(entry) => Ok(entry.get().clone()), + Entry::Vacant(entry) => { + // if you return code bytes when basic fn is called this function is not needed. + Ok(entry.insert(self.db.code_by_hash_ref(code_hash)?).clone()) + } + } + } + + /// Get the value in an account's storage slot. + /// + /// It is assumed that account is already loaded. + fn storage(&mut self, address: Address, index: U256) -> Result { + match self.accounts.entry(address) { + Entry::Occupied(mut acc_entry) => { + let acc_entry = acc_entry.get_mut(); + match acc_entry.storage.entry(index) { + Entry::Occupied(entry) => Ok(*entry.get()), + Entry::Vacant(entry) => { + if matches!( + acc_entry.account_state, + AccountState::StorageCleared | AccountState::NotExisting + ) { + Ok(U256::ZERO) + } else { + let slot = self.db.storage_ref(address, index)?; + entry.insert(slot); + Ok(slot) + } + } + } + } + Entry::Vacant(acc_entry) => { + // acc needs to be loaded for us to access slots. + let info = self.db.basic_ref(address)?; + let (account, value) = if info.is_some() { + let value = self.db.storage_ref(address, index)?; + let mut account: DbAccount = info.into(); + account.storage.insert(index, value); + (account, value) + } else { + (info.into(), U256::ZERO) + }; + acc_entry.insert(account); + Ok(value) + } + } + } + + fn block_hash(&mut self, number: U256) -> Result { + match self.block_hashes.entry(number) { + Entry::Occupied(entry) => Ok(*entry.get()), + Entry::Vacant(entry) => { + let hash = self.db.block_hash_ref(number)?; + entry.insert(hash); + Ok(hash) + } + } + } +} + +impl DatabaseRef for CacheDB { + type Error = ExtDB::Error; + + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + match self.accounts.get(&address) { + Some(acc) => Ok(acc.info()), + None => self.db.basic_ref(address), + } + } + + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + match self.contracts.get(&code_hash) { + Some(entry) => Ok(entry.clone()), + None => self.db.code_by_hash_ref(code_hash), + } + } + + fn storage_ref(&self, address: Address, index: U256) -> Result { + match self.accounts.get(&address) { + Some(acc_entry) => match acc_entry.storage.get(&index) { + Some(entry) => Ok(*entry), + None => { + if matches!( + acc_entry.account_state, + AccountState::StorageCleared | AccountState::NotExisting + ) { + Ok(U256::ZERO) + } else { + self.db.storage_ref(address, index) + } + } + }, + None => self.db.storage_ref(address, index), + } + } + + fn block_hash_ref(&self, number: U256) -> Result { + match self.block_hashes.get(&number) { + Some(entry) => Ok(*entry), + None => self.db.block_hash_ref(number), + } + } +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct DbAccount { + pub info: AccountInfo, + /// If account is selfdestructed or newly created, storage will be cleared. + pub account_state: AccountState, + /// storage slots + pub storage: HashMap, +} + +impl DbAccount { + pub fn new_not_existing() -> Self { + Self { + account_state: AccountState::NotExisting, + ..Default::default() + } + } + + pub fn info(&self) -> Option { + if matches!(self.account_state, AccountState::NotExisting) { + None + } else { + Some(self.info.clone()) + } + } +} + +impl From> for DbAccount { + fn from(from: Option) -> Self { + from.map(Self::from).unwrap_or_else(Self::new_not_existing) + } +} + +impl From for DbAccount { + fn from(info: AccountInfo) -> Self { + Self { + info, + account_state: AccountState::None, + ..Default::default() + } + } +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum AccountState { + /// Before Spurious Dragon hardfork there was a difference between empty and not existing. + /// And we are flagging it here. + NotExisting, + /// EVM touched this account. For newer hardfork this means it can be cleared/removed from state. + Touched, + /// EVM cleared storage of this account, mostly by selfdestruct, we don't ask database for storage slots + /// and assume they are U256::ZERO + StorageCleared, + /// EVM didn't interacted with this account + #[default] + None, +} + +impl AccountState { + /// Returns `true` if EVM cleared storage of this account + pub fn is_storage_cleared(&self) -> bool { + matches!(self, AccountState::StorageCleared) + } +} + +/// Custom benchmarking DB that only has account info for the zero address. +/// +/// Any other address will return an empty account. +#[derive(Debug, Default, Clone)] +pub struct BenchmarkDB(pub Bytecode, B256); + +impl BenchmarkDB { + pub fn new_bytecode(bytecode: Bytecode) -> Self { + let hash = bytecode.hash_slow(); + Self(bytecode, hash) + } +} + +impl Database for BenchmarkDB { + type Error = Infallible; + /// Get basic account information. + fn basic(&mut self, address: Address) -> Result, Self::Error> { + if address == Address::ZERO { + return Ok(Some(AccountInfo { + nonce: 1, + balance: U256::from(10000000), + code: Some(self.0.clone()), + code_hash: self.1, + })); + } + if address == Address::with_last_byte(1) { + return Ok(Some(AccountInfo { + nonce: 0, + balance: U256::from(10000000), + code: None, + code_hash: KECCAK_EMPTY, + })); + } + Ok(None) + } + + /// Get account code by its hash + fn code_by_hash(&mut self, _code_hash: B256) -> Result { + Ok(Bytecode::default()) + } + + /// Get storage value of address at index. + fn storage(&mut self, _address: Address, _index: U256) -> Result { + Ok(U256::default()) + } + + // History related + fn block_hash(&mut self, _number: U256) -> Result { + Ok(B256::default()) + } +} + +#[cfg(test)] +mod tests { + use super::{CacheDB, EmptyDB}; + use crate::primitives::{db::Database, AccountInfo, Address, U256}; + + #[test] + fn test_insert_account_storage() { + let account = Address::with_last_byte(42); + let nonce = 42; + let mut init_state = CacheDB::new(EmptyDB::default()); + init_state.insert_account_info( + account, + AccountInfo { + nonce, + ..Default::default() + }, + ); + + let (key, value) = (U256::from(123), U256::from(456)); + let mut new_state = CacheDB::new(init_state); + new_state + .insert_account_storage(account, key, value) + .unwrap(); + + assert_eq!(new_state.basic(account).unwrap().unwrap().nonce, nonce); + assert_eq!(new_state.storage(account, key), Ok(value)); + } + + #[test] + fn test_replace_account_storage() { + let account = Address::with_last_byte(42); + let nonce = 42; + let mut init_state = CacheDB::new(EmptyDB::default()); + init_state.insert_account_info( + account, + AccountInfo { + nonce, + ..Default::default() + }, + ); + + let (key0, value0) = (U256::from(123), U256::from(456)); + let (key1, value1) = (U256::from(789), U256::from(999)); + init_state + .insert_account_storage(account, key0, value0) + .unwrap(); + + let mut new_state = CacheDB::new(init_state); + new_state + .replace_account_storage(account, [(key1, value1)].into()) + .unwrap(); + + assert_eq!(new_state.basic(account).unwrap().unwrap().nonce, nonce); + assert_eq!(new_state.storage(account, key0), Ok(U256::ZERO)); + assert_eq!(new_state.storage(account, key1), Ok(value1)); + } + + #[cfg(feature = "serde-json")] + #[test] + fn test_serialize_deserialize_cachedb() { + let account = Address::with_last_byte(69); + let nonce = 420; + let mut init_state = CacheDB::new(EmptyDB::default()); + init_state.insert_account_info( + account, + AccountInfo { + nonce, + ..Default::default() + }, + ); + + let serialized = serde_json::to_string(&init_state).unwrap(); + let deserialized: CacheDB = serde_json::from_str(&serialized).unwrap(); + + assert!(deserialized.accounts.get(&account).is_some()); + assert_eq!( + deserialized.accounts.get(&account).unwrap().info.nonce, + nonce + ); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states.md new file mode 100644 index 00000000..b9ca79a8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states.md @@ -0,0 +1,32 @@ +# ๐Ÿฆ€ states.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states.rs) + +```rust +pub mod account_status; +pub mod bundle_account; +pub mod bundle_state; +pub mod cache; +pub mod cache_account; +pub mod changes; +pub mod plain_account; +pub mod reverts; +pub mod state; +pub mod state_builder; +pub mod transition_account; +pub mod transition_state; + +/// Account status for Block and Bundle states. +pub use account_status::AccountStatus; +pub use bundle_account::BundleAccount; +pub use bundle_state::{BundleBuilder, BundleState, OriginalValuesKnown}; +pub use cache::CacheState; +pub use cache_account::CacheAccount; +pub use changes::{PlainStateReverts, PlainStorageChangeset, PlainStorageRevert, StateChangeset}; +pub use plain_account::{PlainAccount, StorageWithOriginalValues}; +pub use reverts::{AccountRevert, RevertToSlot}; +pub use state::{DBBox, State, StateDBBox}; +pub use state_builder::StateBuilder; +pub use transition_account::TransitionAccount; +pub use transition_state::TransitionState; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/account_status.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/account_status.md new file mode 100644 index 00000000..b049838d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/account_status.md @@ -0,0 +1,258 @@ +# ๐Ÿฆ€ account_status.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/account_status.rs) + +```rust +/// After account get loaded from database it can be in a lot of different states +/// while we execute multiple transaction and even blocks over account that is in memory. +/// This structure models all possible states that account can be in. +#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Hash)] +pub enum AccountStatus { + #[default] + LoadedNotExisting, + Loaded, + LoadedEmptyEIP161, + InMemoryChange, + Changed, + Destroyed, + DestroyedChanged, + DestroyedAgain, +} + +impl AccountStatus { + /// Account is not modified and just loaded from database. + pub fn is_not_modified(&self) -> bool { + matches!( + self, + AccountStatus::LoadedNotExisting + | AccountStatus::Loaded + | AccountStatus::LoadedEmptyEIP161 + ) + } + + /// Account was destroyed by calling SELFDESTRUCT. + /// This means that full account and storage are inside memory. + pub fn was_destroyed(&self) -> bool { + matches!( + self, + AccountStatus::Destroyed + | AccountStatus::DestroyedChanged + | AccountStatus::DestroyedAgain + ) + } + + /// This means storage is known, it can be newly created or storage got destroyed. + pub fn is_storage_known(&self) -> bool { + matches!( + self, + AccountStatus::LoadedNotExisting + | AccountStatus::InMemoryChange + | AccountStatus::Destroyed + | AccountStatus::DestroyedChanged + | AccountStatus::DestroyedAgain + ) + } + + /// Account is modified but not destroyed. + /// This means that some storage values can be found in both + /// memory and database. + pub fn is_modified_and_not_destroyed(&self) -> bool { + matches!(self, AccountStatus::Changed | AccountStatus::InMemoryChange) + } + + /// Returns the next account status on creation. + pub fn on_created(&self) -> AccountStatus { + match self { + // if account was destroyed previously just copy new info to it. + AccountStatus::DestroyedAgain + | AccountStatus::Destroyed + | AccountStatus::DestroyedChanged => AccountStatus::DestroyedChanged, + // if account is loaded from db. + AccountStatus::LoadedNotExisting + // Loaded empty eip161 to creates is not possible as CREATE2 was added after EIP-161 + | AccountStatus::LoadedEmptyEIP161 + | AccountStatus::Loaded + | AccountStatus::Changed + | AccountStatus::InMemoryChange => { + // If account is loaded and not empty this means that account has some balance. + // This means that account cannot be created. + // We are assuming that EVM did necessary checks before allowing account to be created. + AccountStatus::InMemoryChange + } + } + } + + /// Returns the next account status on touched empty account post state clear EIP (EIP-161). + /// + /// # Panics + /// + /// If current status is [AccountStatus::Loaded] or [AccountStatus::Changed]. + pub fn on_touched_empty_post_eip161(&self) -> AccountStatus { + match self { + // Account can be touched but not existing. The status should remain the same. + AccountStatus::LoadedNotExisting => AccountStatus::LoadedNotExisting, + // Account can be created empty and only then touched. + AccountStatus::InMemoryChange + | AccountStatus::Destroyed + | AccountStatus::LoadedEmptyEIP161 => AccountStatus::Destroyed, + // Transition to destroy the account. + AccountStatus::DestroyedAgain | AccountStatus::DestroyedChanged => { + AccountStatus::DestroyedAgain + } + // Account statuses considered unreachable. + AccountStatus::Loaded | AccountStatus::Changed => { + unreachable!("Wrong state transition, touch empty is not possible from {self:?}"); + } + } + } + + /// Returns the next account status on touched or created account pre state clear EIP (EIP-161). + /// Returns `None` if the account status didn't change. + /// + /// # Panics + /// + /// If current status is [AccountStatus::Loaded] or [AccountStatus::Changed]. + pub fn on_touched_created_pre_eip161(&self, had_no_info: bool) -> Option { + match self { + AccountStatus::LoadedEmptyEIP161 => None, + AccountStatus::DestroyedChanged => { + if had_no_info { + None + } else { + Some(AccountStatus::DestroyedChanged) + } + } + AccountStatus::Destroyed | AccountStatus::DestroyedAgain => { + Some(AccountStatus::DestroyedChanged) + } + AccountStatus::InMemoryChange | AccountStatus::LoadedNotExisting => { + Some(AccountStatus::InMemoryChange) + } + AccountStatus::Loaded | AccountStatus::Changed => { + unreachable!("Wrong state transition, touch crate is not possible from {self:?}") + } + } + } + + /// Returns the next account status on change. + pub fn on_changed(&self, had_no_nonce_and_code: bool) -> AccountStatus { + match self { + // If the account was loaded as not existing, promote it to changed. + // This account was likely created by a balance transfer. + AccountStatus::LoadedNotExisting => AccountStatus::InMemoryChange, + // Change on empty account, should transfer storage if there is any. + // There is possibility that there are storage entries inside db. + // That storage is used in merkle tree calculation before state clear EIP. + AccountStatus::LoadedEmptyEIP161 => AccountStatus::InMemoryChange, + // The account was loaded as existing. + AccountStatus::Loaded => { + if had_no_nonce_and_code { + // account is fully in memory + AccountStatus::InMemoryChange + } else { + // can be contract and some of storage slots can be present inside db. + AccountStatus::Changed + } + } + + // On change, the "changed" type account statuses are preserved. + // Any checks for empty accounts are done outside of this fn. + AccountStatus::Changed => AccountStatus::Changed, + AccountStatus::InMemoryChange => AccountStatus::InMemoryChange, + AccountStatus::DestroyedChanged => AccountStatus::DestroyedChanged, + + // If account is destroyed and then changed this means this is + // balance transfer. + AccountStatus::Destroyed | AccountStatus::DestroyedAgain => { + AccountStatus::DestroyedChanged + } + } + } + + /// Returns the next account status on selfdestruct. + pub fn on_selfdestructed(&self) -> AccountStatus { + match self { + // Non existing account can't be destroyed. + AccountStatus::LoadedNotExisting => AccountStatus::LoadedNotExisting, + // If account is created and selfdestructed in the same block, mark it as destroyed again. + // Note: there is no big difference between Destroyed and DestroyedAgain in this case, + // but was added for clarity. + AccountStatus::DestroyedChanged + | AccountStatus::DestroyedAgain + | AccountStatus::Destroyed => AccountStatus::DestroyedAgain, + + // Transition to destroyed status. + _ => AccountStatus::Destroyed, + } + } + + /// Transition to other state while preserving invariance of this state. + /// + /// It this account was Destroyed and other account is not: + /// we should mark extended account as destroyed too. + /// and as other account had some changes, extended account + /// should be marked as DestroyedChanged. + /// + /// If both account are not destroyed and if this account is in memory: + /// this means that extended account is in memory too. + /// + /// Otherwise, if both are destroyed or other is destroyed: + /// set other status to extended account. + pub fn transition(&mut self, other: Self) { + *self = match (self.was_destroyed(), other.was_destroyed()) { + (true, false) => Self::DestroyedChanged, + (false, false) if *self == Self::InMemoryChange => Self::InMemoryChange, + _ => other, + }; + } +} + +#[cfg(test)] +mod test { + + use super::*; + + #[test] + fn test_account_status() { + // account not modified + assert!(AccountStatus::Loaded.is_not_modified()); + assert!(AccountStatus::LoadedEmptyEIP161.is_not_modified()); + assert!(AccountStatus::LoadedNotExisting.is_not_modified()); + assert!(!AccountStatus::Changed.is_not_modified()); + assert!(!AccountStatus::InMemoryChange.is_not_modified()); + assert!(!AccountStatus::Destroyed.is_not_modified()); + assert!(!AccountStatus::DestroyedChanged.is_not_modified()); + assert!(!AccountStatus::DestroyedAgain.is_not_modified()); + + // we know full storage + assert!(!AccountStatus::LoadedEmptyEIP161.is_storage_known()); + assert!(AccountStatus::LoadedNotExisting.is_storage_known()); + assert!(AccountStatus::InMemoryChange.is_storage_known()); + assert!(AccountStatus::Destroyed.is_storage_known()); + assert!(AccountStatus::DestroyedChanged.is_storage_known()); + assert!(AccountStatus::DestroyedAgain.is_storage_known()); + assert!(!AccountStatus::Loaded.is_storage_known()); + assert!(!AccountStatus::Changed.is_storage_known()); + + // account was destroyed + assert!(!AccountStatus::LoadedEmptyEIP161.was_destroyed()); + assert!(!AccountStatus::LoadedNotExisting.was_destroyed()); + assert!(!AccountStatus::InMemoryChange.was_destroyed()); + assert!(AccountStatus::Destroyed.was_destroyed()); + assert!(AccountStatus::DestroyedChanged.was_destroyed()); + assert!(AccountStatus::DestroyedAgain.was_destroyed()); + assert!(!AccountStatus::Loaded.was_destroyed()); + assert!(!AccountStatus::Changed.was_destroyed()); + + // account modified but not destroyed + assert!(AccountStatus::Changed.is_modified_and_not_destroyed()); + assert!(AccountStatus::InMemoryChange.is_modified_and_not_destroyed()); + assert!(!AccountStatus::Loaded.is_modified_and_not_destroyed()); + assert!(!AccountStatus::LoadedEmptyEIP161.is_modified_and_not_destroyed()); + assert!(!AccountStatus::LoadedNotExisting.is_modified_and_not_destroyed()); + assert!(!AccountStatus::Destroyed.is_modified_and_not_destroyed()); + assert!(!AccountStatus::DestroyedChanged.is_modified_and_not_destroyed()); + assert!(!AccountStatus::DestroyedAgain.is_modified_and_not_destroyed()); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/bundle_account.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/bundle_account.md new file mode 100644 index 00000000..5d3aab32 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/bundle_account.md @@ -0,0 +1,375 @@ +# ๐Ÿฆ€ bundle_account.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/bundle_account.rs) + +```rust +use super::{ + reverts::AccountInfoRevert, AccountRevert, AccountStatus, RevertToSlot, + StorageWithOriginalValues, TransitionAccount, +}; +use revm_interpreter::primitives::{AccountInfo, StorageSlot, U256}; +use revm_precompile::HashMap; + +/// Account information focused on creating of database changesets +/// and Reverts. +/// +/// Status is needed as to know from what state we are applying the TransitionAccount. +/// +/// Original account info is needed to know if there was a change. +/// Same thing for storage with original value. +/// +/// On selfdestruct storage original value is ignored. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BundleAccount { + pub info: Option, + pub original_info: Option, + /// Contains both original and present state. + /// When extracting changeset we compare if original value is different from present value. + /// If it is different we add it to changeset. + /// + /// If Account was destroyed we ignore original value and compare present state with U256::ZERO. + pub storage: StorageWithOriginalValues, + /// Account status. + pub status: AccountStatus, +} + +impl BundleAccount { + /// Create new BundleAccount. + pub fn new( + original_info: Option, + present_info: Option, + storage: StorageWithOriginalValues, + status: AccountStatus, + ) -> Self { + Self { + info: present_info, + original_info, + storage, + status, + } + } + + /// The approximate size of changes needed to store this account. + /// `1 + storage_len` + pub fn size_hint(&self) -> usize { + 1 + self.storage.len() + } + + /// Return storage slot if it exists. + /// + /// In case we know that account is newly created or destroyed, return `Some(U256::ZERO)` + pub fn storage_slot(&self, slot: U256) -> Option { + let slot = self.storage.get(&slot).map(|s| s.present_value); + if slot.is_some() { + slot + } else if self.status.is_storage_known() { + Some(U256::ZERO) + } else { + None + } + } + + /// Fetch account info if it exist. + pub fn account_info(&self) -> Option { + self.info.clone() + } + + /// Was this account destroyed. + pub fn was_destroyed(&self) -> bool { + self.status.was_destroyed() + } + + /// Return true of account info was changed. + pub fn is_info_changed(&self) -> bool { + self.info != self.original_info + } + + /// Return true if contract was changed + pub fn is_contract_changed(&self) -> bool { + self.info.as_ref().map(|a| a.code_hash) != self.original_info.as_ref().map(|a| a.code_hash) + } + + /// Revert account to previous state and return true if account can be removed. + pub fn revert(&mut self, revert: AccountRevert) -> bool { + self.status = revert.previous_status; + + match revert.account { + AccountInfoRevert::DoNothing => (), + AccountInfoRevert::DeleteIt => { + self.info = None; + if self.original_info.is_none() { + self.storage = HashMap::new(); + return true; + } else { + // set all storage to zero but preserve original values. + self.storage.iter_mut().for_each(|(_, v)| { + v.present_value = U256::ZERO; + }); + return false; + } + } + AccountInfoRevert::RevertTo(info) => self.info = Some(info), + }; + // revert storage + for (key, slot) in revert.storage { + match slot { + RevertToSlot::Some(value) => { + // Don't overwrite original values if present + // if storage is not present set original value as current value. + self.storage + .entry(key) + .or_insert(StorageSlot::new(value)) + .present_value = value; + } + RevertToSlot::Destroyed => { + // if it was destroyed this means that storage was created and we need to remove it. + self.storage.remove(&key); + } + } + } + false + } + + /// Update to new state and generate AccountRevert that if applied to new state will + /// revert it to previous state. If no revert is present, update is noop. + pub fn update_and_create_revert( + &mut self, + transition: TransitionAccount, + ) -> Option { + let updated_info = transition.info; + let updated_storage = transition.storage; + let updated_status = transition.status; + + // the helper that extends this storage but preserves original value. + let extend_storage = + |this_storage: &mut StorageWithOriginalValues, + storage_update: StorageWithOriginalValues| { + for (key, value) in storage_update { + this_storage.entry(key).or_insert(value).present_value = value.present_value; + } + }; + + let previous_storage_from_update = + |updated_storage: &StorageWithOriginalValues| -> HashMap { + updated_storage + .iter() + .filter(|s| s.1.is_changed()) + .map(|(key, value)| { + (*key, RevertToSlot::Some(value.previous_or_original_value)) + }) + .collect() + }; + + // Needed for some reverts. + let info_revert = if self.info != updated_info { + AccountInfoRevert::RevertTo(self.info.clone().unwrap_or_default()) + } else { + AccountInfoRevert::DoNothing + }; + + let account_revert = match updated_status { + AccountStatus::Changed => { + let previous_storage = previous_storage_from_update(&updated_storage); + match self.status { + AccountStatus::Changed | AccountStatus::Loaded => { + // extend the storage. original values is not used inside bundle. + extend_storage(&mut self.storage, updated_storage); + } + AccountStatus::LoadedEmptyEIP161 => { + // Do nothing. + // Only change that can happen from LoadedEmpty to Changed is if balance + // is send to account. So we are only checking account change here. + } + _ => unreachable!("Invalid state transfer to Changed from {self:?}"), + }; + let previous_status = self.status; + self.status = AccountStatus::Changed; + self.info = updated_info; + Some(AccountRevert { + account: info_revert, + storage: previous_storage, + previous_status, + wipe_storage: false, + }) + } + AccountStatus::InMemoryChange => { + let previous_storage = previous_storage_from_update(&updated_storage); + let in_memory_info_revert = match self.status { + AccountStatus::Loaded | AccountStatus::InMemoryChange => { + // from loaded (Or LoadedEmpty) to InMemoryChange can happen if there is balance change + // or new created account but Loaded didn't have contract. + extend_storage(&mut self.storage, updated_storage); + info_revert + } + AccountStatus::LoadedEmptyEIP161 => { + self.storage = updated_storage; + info_revert + } + AccountStatus::LoadedNotExisting => { + self.storage = updated_storage; + AccountInfoRevert::DeleteIt + } + _ => unreachable!("Invalid change to InMemoryChange from {self:?}"), + }; + let previous_status = self.status; + self.status = AccountStatus::InMemoryChange; + self.info = updated_info; + Some(AccountRevert { + account: in_memory_info_revert, + storage: previous_storage, + previous_status, + wipe_storage: false, + }) + } + AccountStatus::Loaded + | AccountStatus::LoadedNotExisting + | AccountStatus::LoadedEmptyEIP161 => { + // No changeset, maybe just update data + // Do nothing for now. + None + } + AccountStatus::Destroyed => { + // clear this storage and move it to the Revert. + let this_storage = self.storage.drain().collect(); + let ret = match self.status { + AccountStatus::InMemoryChange | AccountStatus::Changed | AccountStatus::Loaded | AccountStatus::LoadedEmptyEIP161 => { + Some(AccountRevert::new_selfdestructed(self.status, info_revert, this_storage)) + } + AccountStatus::LoadedNotExisting => { + // Do nothing as we have LoadedNotExisting -> Destroyed (It is noop) + None + } + _ => unreachable!("Invalid transition to Destroyed account from: {self:?} to {updated_info:?} {updated_status:?}"), + }; + + if ret.is_some() { + self.status = AccountStatus::Destroyed; + self.info = None; + } + + // set present to destroyed. + ret + } + AccountStatus::DestroyedChanged => { + // Previous block created account or changed. + // (It was destroyed on previous block or one before). + + // check common pre destroy paths. + // If common path is there it will drain the storage. + if let Some(revert_state) = AccountRevert::new_selfdestructed_from_bundle( + info_revert.clone(), + self, + &updated_storage, + ) { + // set to destroyed and revert state. + self.status = AccountStatus::DestroyedChanged; + self.info = updated_info; + self.storage = updated_storage; + + Some(revert_state) + } else { + let ret = match self.status { + AccountStatus::Destroyed | AccountStatus::LoadedNotExisting => { + // from destroyed state new account is made + Some(AccountRevert { + account: AccountInfoRevert::DeleteIt, + storage: previous_storage_from_update(&updated_storage), + previous_status: self.status, + wipe_storage: false, + }) + } + AccountStatus::DestroyedChanged => { + // Account was destroyed in this transition. So we should clear present storage + // and insert it inside revert. + + let previous_storage = if transition.storage_was_destroyed { + let mut storage = core::mem::take(&mut self.storage) + .into_iter() + .map(|t| (t.0, RevertToSlot::Some(t.1.present_value))) + .collect::>(); + for key in updated_storage.keys() { + // as it is not existing inside Destroyed storage this means + // that previous values must be zero + storage.entry(*key).or_insert(RevertToSlot::Destroyed); + } + storage + } else { + previous_storage_from_update(&updated_storage) + }; + + Some(AccountRevert { + account: info_revert, + storage: previous_storage, + previous_status: AccountStatus::DestroyedChanged, + wipe_storage: false, + }) + } + AccountStatus::DestroyedAgain => { + Some(AccountRevert::new_selfdestructed_again( + // destroyed again will set empty account. + AccountStatus::DestroyedAgain, + AccountInfoRevert::DeleteIt, + HashMap::default(), + updated_storage.clone(), + )) + } + _ => unreachable!("Invalid state transfer to DestroyedNew from {self:?}"), + }; + self.status = AccountStatus::DestroyedChanged; + self.info = updated_info; + // extends current storage. + extend_storage(&mut self.storage, updated_storage); + + ret + } + } + AccountStatus::DestroyedAgain => { + // Previous block created account + // (It was destroyed on previous block or one before). + + // check common pre destroy paths. + // This will drain the storage if it is common transition. + let ret = if let Some(revert_state) = AccountRevert::new_selfdestructed_from_bundle( + info_revert, + self, + &HashMap::default(), + ) { + Some(revert_state) + } else { + match self.status { + AccountStatus::Destroyed + | AccountStatus::DestroyedAgain + | AccountStatus::LoadedNotExisting => { + // From destroyed to destroyed again. is noop + // + // DestroyedAgain to DestroyedAgain is noop + // + // From LoadedNotExisting to DestroyedAgain + // is noop as account is destroyed again + None + } + AccountStatus::DestroyedChanged => { + // From destroyed changed to destroyed again. + Some(AccountRevert::new_selfdestructed_again( + // destroyed again will set empty account. + AccountStatus::DestroyedChanged, + AccountInfoRevert::RevertTo(self.info.clone().unwrap_or_default()), + self.storage.drain().collect(), + HashMap::default(), + )) + } + _ => unreachable!("Invalid state to DestroyedAgain from {self:?}"), + } + }; + // set to destroyed and revert state. + self.status = AccountStatus::DestroyedAgain; + self.info = None; + self.storage.clear(); + ret + } + }; + + account_revert.and_then(|acc| if acc.is_empty() { None } else { Some(acc) }) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/bundle_state.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/bundle_state.md new file mode 100644 index 00000000..f67e36c8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/bundle_state.md @@ -0,0 +1,1110 @@ +# ๐Ÿฆ€ bundle_state.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/bundle_state.rs) + +```rust +use super::{ + changes::{PlainStorageChangeset, StateChangeset}, + reverts::{AccountInfoRevert, Reverts}, + AccountRevert, AccountStatus, BundleAccount, PlainStateReverts, RevertToSlot, TransitionState, +}; +use core::{mem, ops::RangeInclusive}; +use revm_interpreter::primitives::{ + hash_map::{self, Entry}, + AccountInfo, Address, Bytecode, HashMap, HashSet, StorageSlot, B256, KECCAK_EMPTY, U256, +}; +use std::{ + collections::{BTreeMap, BTreeSet}, + vec::Vec, +}; + +/// This builder is used to help to facilitate the initialization of `BundleState` struct +#[derive(Debug)] +pub struct BundleBuilder { + states: HashSet
, + state_original: HashMap, + state_present: HashMap, + state_storage: HashMap>, + + reverts: BTreeSet<(u64, Address)>, + revert_range: RangeInclusive, + revert_account: HashMap<(u64, Address), Option>>, + revert_storage: HashMap<(u64, Address), Vec<(U256, U256)>>, + + contracts: HashMap, +} + +/// Option for [`BundleState`] when converting it to the plain state. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum OriginalValuesKnown { + /// Check changed with original values that [BundleState] has. + /// + /// If we don't expect parent blocks to be committed or unwinded from database, this option + /// should be used. + Yes, + /// Don't check original values, see the implementation of [BundleState::into_plain_state] for + /// more info. + /// + /// If the Bundle can be split or extended, we would not be sure about original values, in that + /// case this option should be used. + No, +} +impl OriginalValuesKnown { + /// Original value is not known for sure. + pub fn is_not_known(&self) -> bool { + matches!(self, Self::No) + } +} + +impl Default for BundleBuilder { + fn default() -> Self { + BundleBuilder { + states: HashSet::new(), + state_original: HashMap::new(), + state_present: HashMap::new(), + state_storage: HashMap::new(), + reverts: BTreeSet::new(), + revert_range: 0..=0, + revert_account: HashMap::new(), + revert_storage: HashMap::new(), + contracts: HashMap::new(), + } + } +} + +impl BundleBuilder { + /// Create builder instance + /// + /// `revert_range` indicates the size of BundleState `reverts` field + pub fn new(revert_range: RangeInclusive) -> Self { + BundleBuilder { + revert_range, + ..Default::default() + } + } + + /// Collect address info of BundleState state + pub fn state_address(mut self, address: Address) -> Self { + self.states.insert(address); + self + } + + /// Collect account info of BundleState state + pub fn state_original_account_info(mut self, address: Address, original: AccountInfo) -> Self { + self.states.insert(address); + self.state_original.insert(address, original); + self + } + + /// Collect account info of BundleState state + pub fn state_present_account_info(mut self, address: Address, present: AccountInfo) -> Self { + self.states.insert(address); + self.state_present.insert(address, present); + self + } + + /// Collect storage info of BundleState state + pub fn state_storage(mut self, address: Address, storage: HashMap) -> Self { + self.states.insert(address); + self.state_storage.insert(address, storage); + self + } + + /// Collect address info of BundleState reverts + /// + /// `block_number` must respect `revert_range`, or the input + /// will be ignored during the final build process + pub fn revert_address(mut self, block_number: u64, address: Address) -> Self { + self.reverts.insert((block_number, address)); + self + } + + /// Collect account info of BundleState reverts + /// + /// `block_number` must respect `revert_range`, or the input + /// will be ignored during the final build process + pub fn revert_account_info( + mut self, + block_number: u64, + address: Address, + account: Option>, + ) -> Self { + self.reverts.insert((block_number, address)); + self.revert_account.insert((block_number, address), account); + self + } + + /// Collect storage info of BundleState reverts + /// + /// `block_number` must respect `revert_range`, or the input + /// will be ignored during the final build process + pub fn revert_storage( + mut self, + block_number: u64, + address: Address, + storage: Vec<(U256, U256)>, + ) -> Self { + self.reverts.insert((block_number, address)); + self.revert_storage.insert((block_number, address), storage); + self + } + + /// Collect contracts info + pub fn contract(mut self, address: B256, bytecode: Bytecode) -> Self { + self.contracts.insert(address, bytecode); + self + } + + /// Create `BundleState` instance based on collected information + pub fn build(mut self) -> BundleState { + let mut state_size = 0; + let state = self + .states + .into_iter() + .map(|address| { + let storage = self + .state_storage + .remove(&address) + .map(|s| { + s.into_iter() + .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val))) + .collect() + }) + .unwrap_or_default(); + let bundle_account = BundleAccount::new( + self.state_original.remove(&address), + self.state_present.remove(&address), + storage, + AccountStatus::Changed, + ); + state_size += bundle_account.size_hint(); + (address, bundle_account) + }) + .collect(); + + let mut reverts_size = 0; + let mut reverts_map = BTreeMap::new(); + for block_number in self.revert_range { + reverts_map.insert(block_number, Vec::new()); + } + self.reverts + .into_iter() + .for_each(|(block_number, address)| { + let account = match self + .revert_account + .remove(&(block_number, address)) + .unwrap_or_default() + { + Some(Some(account)) => AccountInfoRevert::RevertTo(account), + Some(None) => AccountInfoRevert::DeleteIt, + None => AccountInfoRevert::DoNothing, + }; + let storage = self + .revert_storage + .remove(&(block_number, address)) + .map(|s| { + s.into_iter() + .map(|(k, v)| (k, RevertToSlot::Some(v))) + .collect() + }) + .unwrap_or_default(); + let account_revert = AccountRevert { + account, + storage, + previous_status: AccountStatus::Changed, + wipe_storage: false, + }; + + if reverts_map.contains_key(&block_number) { + reverts_size += account_revert.size_hint(); + reverts_map + .entry(block_number) + .or_insert(Vec::new()) + .push((address, account_revert)); + } + }); + + BundleState { + state, + contracts: self.contracts, + reverts: Reverts::new(reverts_map.into_values().collect()), + state_size, + reverts_size, + } + } + + /// Getter for `states` field + pub fn get_states(&self) -> &HashSet
{ + &self.states + } +} + +/// Bundle retention policy for applying substate to the bundle. +#[derive(Debug)] +pub enum BundleRetention { + /// Only plain state is updated. + PlainState, + /// Both, plain state and reverts, are retained + Reverts, +} + +impl BundleRetention { + /// Returns `true` if reverts should be retained. + pub fn includes_reverts(&self) -> bool { + matches!(self, Self::Reverts) + } +} + +/// Bundle state contain only values that got changed +/// +/// For every account it contains both original and present state. +/// This is needed to decide if there were any changes to the account. +/// +/// Reverts and created when TransitionState is applied to BundleState. +/// And can be used to revert BundleState to the state before transition. +#[derive(Default, Clone, Debug, PartialEq, Eq)] +pub struct BundleState { + /// Account state. + pub state: HashMap, + /// All created contracts in this block. + pub contracts: HashMap, + /// Changes to revert. + /// + /// Note: Inside vector is *not* sorted by address. + /// But it is unique by address. + pub reverts: Reverts, + /// The size of the plain state in the bundle state. + pub state_size: usize, + /// The size of reverts in the bundle state. + pub reverts_size: usize, +} + +impl BundleState { + /// Return builder instance for further manipulation + pub fn builder(revert_range: RangeInclusive) -> BundleBuilder { + BundleBuilder::new(revert_range) + } + + /// Create it with new and old values of both Storage and AccountInfo. + pub fn new( + state: impl IntoIterator< + Item = ( + Address, + Option, + Option, + HashMap, + ), + >, + reverts: impl IntoIterator< + Item = impl IntoIterator< + Item = ( + Address, + Option>, + impl IntoIterator, + ), + >, + >, + contracts: impl IntoIterator, + ) -> Self { + // Create state from iterator. + let mut state_size = 0; + let state = state + .into_iter() + .map(|(address, original, present, storage)| { + let account = BundleAccount::new( + original, + present, + storage + .into_iter() + .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val))) + .collect(), + AccountStatus::Changed, + ); + state_size += account.size_hint(); + (address, account) + }) + .collect(); + + // Create reverts from iterator. + let mut reverts_size = 0; + let reverts = reverts + .into_iter() + .map(|block_reverts| { + block_reverts + .into_iter() + .map(|(address, account, storage)| { + let account = match account { + Some(Some(account)) => AccountInfoRevert::RevertTo(account), + Some(None) => AccountInfoRevert::DeleteIt, + None => AccountInfoRevert::DoNothing, + }; + let revert = AccountRevert { + account, + storage: storage + .into_iter() + .map(|(k, v)| (k, RevertToSlot::Some(v))) + .collect(), + previous_status: AccountStatus::Changed, + wipe_storage: false, + }; + reverts_size += revert.size_hint(); + (address, revert) + }) + .collect::>() + }) + .collect::>(); + + Self { + state, + contracts: contracts.into_iter().collect(), + reverts: Reverts::new(reverts), + state_size, + reverts_size, + } + } + + /// Returns the approximate size of changes in the bundle state. + /// The estimation is not precise, because the information about the number of + /// destroyed entries that need to be removed is not accessible to the bundle state. + pub fn size_hint(&self) -> usize { + self.state_size + self.reverts_size + self.contracts.len() + } + + /// Return reference to the state. + pub fn state(&self) -> &HashMap { + &self.state + } + + /// Is bundle state empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Return number of changed accounts. + pub fn len(&self) -> usize { + self.state.len() + } + + /// Get account from state + pub fn account(&self, address: &Address) -> Option<&BundleAccount> { + self.state.get(address) + } + + /// Get bytecode from state + pub fn bytecode(&self, hash: &B256) -> Option { + self.contracts.get(hash).cloned() + } + + /// Consume `TransitionState` by applying the changes and creating the reverts + /// + /// If [BundleRetention::includes_reverts] is `true`, then the reverts will be retained. + pub fn apply_transitions_and_create_reverts( + &mut self, + transitions: TransitionState, + retention: BundleRetention, + ) { + let include_reverts = retention.includes_reverts(); + // pessimistically pre-allocate assuming _all_ accounts changed. + let reverts_capacity = if include_reverts { + transitions.transitions.len() + } else { + 0 + }; + let mut reverts = Vec::with_capacity(reverts_capacity); + + for (address, transition) in transitions.transitions.into_iter() { + // add new contract if it was created/changed. + if let Some((hash, new_bytecode)) = transition.has_new_contract() { + self.contracts.insert(hash, new_bytecode.clone()); + } + // update state and create revert. + let revert = match self.state.entry(address) { + hash_map::Entry::Occupied(mut entry) => { + let entry = entry.get_mut(); + self.state_size -= entry.size_hint(); + // update and create revert if it is present + let revert = entry.update_and_create_revert(transition); + // update the state size + self.state_size += entry.size_hint(); + revert + } + hash_map::Entry::Vacant(entry) => { + // make revert from transition account + let present_bundle = transition.present_bundle_account(); + let revert = transition.create_revert(); + if revert.is_some() { + self.state_size += present_bundle.size_hint(); + entry.insert(present_bundle); + } + revert + } + }; + + // append revert if present. + if let Some(revert) = revert.filter(|_| include_reverts) { + self.reverts_size += revert.size_hint(); + reverts.push((address, revert)); + } + } + + self.reverts.push(reverts); + } + + /// Consume the bundle state and return plain state. + pub fn into_plain_state(self, is_value_known: OriginalValuesKnown) -> StateChangeset { + // pessimistically pre-allocate assuming _all_ accounts changed. + let state_len = self.state.len(); + let mut accounts = Vec::with_capacity(state_len); + let mut storage = Vec::with_capacity(state_len); + + for (address, account) in self.state { + // append account info if it is changed. + let was_destroyed = account.was_destroyed(); + if is_value_known.is_not_known() || account.is_info_changed() { + let info = account.info.map(AccountInfo::without_code); + accounts.push((address, info)); + } + + // append storage changes + + // NOTE: Assumption is that revert is going to remove whole plain storage from + // database so we can check if plain state was wiped or not. + let mut account_storage_changed = Vec::with_capacity(account.storage.len()); + + for (key, slot) in account.storage { + // If storage was destroyed that means that storage was wiped. + // In that case we need to check if present storage value is different then ZERO. + let destroyed_and_not_zero = was_destroyed && slot.present_value != U256::ZERO; + + // If account is not destroyed check if original values was changed, + // so we can update it. + let not_destroyed_and_changed = !was_destroyed && slot.is_changed(); + + if is_value_known.is_not_known() + || destroyed_and_not_zero + || not_destroyed_and_changed + { + account_storage_changed.push((key, slot.present_value)); + } + } + + if !account_storage_changed.is_empty() || was_destroyed { + // append storage changes to account. + storage.push(PlainStorageChangeset { + address, + wipe_storage: was_destroyed, + storage: account_storage_changed, + }); + } + } + let contracts = self + .contracts + .into_iter() + // remove empty bytecodes + .filter(|(b, _)| *b != KECCAK_EMPTY) + .collect::>(); + StateChangeset { + accounts, + storage, + contracts, + } + } + + /// Consume the bundle state and split it into reverts and plain state. + pub fn into_plain_state_and_reverts( + mut self, + is_value_known: OriginalValuesKnown, + ) -> (StateChangeset, PlainStateReverts) { + let reverts = self.take_all_reverts(); + let plain_state = self.into_plain_state(is_value_known); + (plain_state, reverts.into_plain_state_reverts()) + } + + /// Extend the bundle with other state + /// + /// Update the `other` state only if `other` is not flagged as destroyed. + pub fn extend_state(&mut self, other_state: HashMap) { + for (address, other_account) in other_state { + match self.state.entry(address) { + hash_map::Entry::Occupied(mut entry) => { + let this = entry.get_mut(); + self.state_size -= this.size_hint(); + + // if other was destroyed. replace `this` storage with + // the `other one. + if other_account.was_destroyed() { + this.storage = other_account.storage; + } else { + // otherwise extend this storage with other + for (key, storage_slot) in other_account.storage { + // update present value or insert storage slot. + this.storage + .entry(key) + .or_insert(storage_slot) + .present_value = storage_slot.present_value; + } + } + this.info = other_account.info; + this.status.transition(other_account.status); + + // Update the state size + self.state_size += this.size_hint(); + } + hash_map::Entry::Vacant(entry) => { + // just insert if empty + self.state_size += other_account.size_hint(); + entry.insert(other_account); + } + } + } + } + /// Extend the state with state that is build on top of it. + /// + /// If storage was wiped in `other` state, copy `this` plain state + /// and put it inside `other` revert (if there is no duplicates of course). + /// + /// If `this` and `other` accounts were both destroyed invalidate second + /// wipe flag (from `other`). As wiping from database should be done only once + /// and we already transferred all potentially missing storages to the `other` revert. + pub fn extend(&mut self, mut other: Self) { + // iterate over reverts and if its storage is wiped try to add previous bundle + // state as there is potential missing slots. + for (address, revert) in other.reverts.iter_mut().flatten() { + if revert.wipe_storage { + // If there is wipe storage in `other` revert + // we need to move storage from present state. + if let Some(this_account) = self.state.get_mut(address) { + // As this account was destroyed inside `other` bundle. + // we are fine to wipe/drain this storage and put it inside revert. + for (key, value) in this_account.storage.drain() { + revert + .storage + .entry(key) + .or_insert(RevertToSlot::Some(value.present_value)); + } + + // nullify `other` wipe as primary database wipe is done in `this`. + if this_account.was_destroyed() { + revert.wipe_storage = false; + } + } + } + + // Increment reverts size for each of the updated reverts. + self.reverts_size += revert.size_hint(); + } + // Extension of state + self.extend_state(other.state); + // Contract can be just extended, when counter is introduced we will take into account that. + self.contracts.extend(other.contracts); + // Reverts can be just extended + self.reverts.extend(other.reverts); + } + + /// Take first N raw reverts from the [BundleState]. + pub fn take_n_reverts(&mut self, reverts_to_take: usize) -> Reverts { + // split is done as [0, num) and [num, len]. + if reverts_to_take > self.reverts.len() { + return self.take_all_reverts(); + } + let (detach, this) = self.reverts.split_at(reverts_to_take); + let detached_reverts = Reverts::new(detach.to_vec()); + self.reverts_size = this + .iter() + .flatten() + .fold(0, |acc, (_, revert)| acc + revert.size_hint()); + self.reverts = Reverts::new(this.to_vec()); + detached_reverts + } + + /// Return and clear all reverts from [BundleState] + pub fn take_all_reverts(&mut self) -> Reverts { + self.reverts_size = 0; + core::mem::take(&mut self.reverts) + } + + /// Reverts the state changes of the latest transition + /// + /// Note: This is the same as `BundleState::revert(1)` + /// + /// Returns true if the state was reverted. + pub fn revert_latest(&mut self) -> bool { + // revert the latest recorded state + if let Some(reverts) = self.reverts.pop() { + for (address, revert_account) in reverts.into_iter() { + self.reverts_size -= revert_account.size_hint(); + match self.state.entry(address) { + Entry::Occupied(mut entry) => { + let account = entry.get_mut(); + self.state_size -= account.size_hint(); + if account.revert(revert_account) { + entry.remove(); + } else { + self.state_size += account.size_hint(); + } + } + Entry::Vacant(entry) => { + // create empty account that we will revert on. + // Only place where this account is not existing is if revert is DeleteIt. + let mut account = BundleAccount::new( + None, + None, + HashMap::new(), + AccountStatus::LoadedNotExisting, + ); + if !account.revert(revert_account) { + self.state_size += account.size_hint(); + entry.insert(account); + } + } + } + } + return true; + } + + false + } + + /// Reverts the state changes by N transitions back. + /// + /// See also [Self::revert_latest] + pub fn revert(&mut self, mut num_transitions: usize) { + if num_transitions == 0 { + return; + } + + while self.revert_latest() { + num_transitions -= 1; + if num_transitions == 0 { + // break the loop. + break; + } + } + } + + /// Prepends present the state with the given BundleState. + /// It adds changes from the given state but does not override any existing changes. + /// + /// Reverts are not updated. + pub fn prepend_state(&mut self, mut other: BundleState) { + // take this bundle + let this_bundle = mem::take(self); + // extend other bundle state with this + other.extend_state(this_bundle.state); + // extend other contracts + other.contracts.extend(this_bundle.contracts); + // swap bundles + mem::swap(self, &mut other) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{db::StorageWithOriginalValues, TransitionAccount}; + + #[test] + fn transition_states() { + // dummy data + let address = Address::new([0x01; 20]); + let acc1 = AccountInfo { + balance: U256::from(10), + nonce: 1, + code_hash: KECCAK_EMPTY, + code: None, + }; + + let mut bundle_state = BundleState::default(); + + // have transition from loaded to all other states + + let transition = TransitionAccount { + info: Some(acc1), + status: AccountStatus::InMemoryChange, + previous_info: None, + previous_status: AccountStatus::LoadedNotExisting, + storage: StorageWithOriginalValues::default(), + storage_was_destroyed: false, + }; + + // apply first transition + bundle_state.apply_transitions_and_create_reverts( + TransitionState::single(address, transition.clone()), + BundleRetention::Reverts, + ); + } + + const fn account1() -> Address { + Address::new([0x60; 20]) + } + + const fn account2() -> Address { + Address::new([0x61; 20]) + } + + fn slot1() -> U256 { + U256::from(5) + } + + fn slot2() -> U256 { + U256::from(7) + } + + /// Test bundle one + fn test_bundle1() -> BundleState { + // block changes + BundleState::new( + vec![ + ( + account1(), + None, + Some(AccountInfo { + nonce: 1, + balance: U256::from(10), + code_hash: KECCAK_EMPTY, + code: None, + }), + HashMap::from([ + (slot1(), (U256::from(0), U256::from(10))), + (slot2(), (U256::from(0), U256::from(15))), + ]), + ), + ( + account2(), + None, + Some(AccountInfo { + nonce: 1, + balance: U256::from(10), + code_hash: KECCAK_EMPTY, + code: None, + }), + HashMap::from([]), + ), + ], + vec![vec![ + ( + account1(), + Some(None), + vec![(slot1(), U256::from(0)), (slot2(), U256::from(0))], + ), + (account2(), Some(None), vec![]), + ]], + vec![], + ) + } + + /// Test bundle two + fn test_bundle2() -> BundleState { + // block changes + BundleState::new( + vec![( + account1(), + None, + Some(AccountInfo { + nonce: 3, + balance: U256::from(20), + code_hash: KECCAK_EMPTY, + code: None, + }), + HashMap::from([(slot1(), (U256::from(0), U256::from(15)))]), + )], + vec![vec![( + account1(), + Some(Some(AccountInfo { + nonce: 1, + balance: U256::from(10), + code_hash: KECCAK_EMPTY, + code: None, + })), + vec![(slot1(), U256::from(10))], + )]], + vec![], + ) + } + + /// Test bundle three + fn test_bundle3() -> BundleState { + BundleState::builder(0..=0) + .state_present_account_info( + account1(), + AccountInfo { + nonce: 1, + balance: U256::from(10), + code_hash: KECCAK_EMPTY, + code: None, + }, + ) + .state_storage( + account1(), + HashMap::from([(slot1(), (U256::from(0), U256::from(10)))]), + ) + .state_address(account2()) + .state_present_account_info( + account2(), + AccountInfo { + nonce: 1, + balance: U256::from(10), + code_hash: KECCAK_EMPTY, + code: None, + }, + ) + .revert_address(0, account1()) + .revert_account_info(0, account1(), Some(None)) + .revert_storage(0, account1(), vec![(slot1(), U256::from(0))]) + .revert_account_info(0, account2(), Some(None)) + .build() + } + + /// Test bundle four + fn test_bundle4() -> BundleState { + BundleState::builder(0..=0) + .state_present_account_info( + account1(), + AccountInfo { + nonce: 3, + balance: U256::from(20), + code_hash: KECCAK_EMPTY, + code: None, + }, + ) + .state_storage( + account1(), + HashMap::from([(slot1(), (U256::from(0), U256::from(15)))]), + ) + .revert_address(0, account1()) + .revert_account_info( + 0, + account1(), + Some(Some(AccountInfo { + nonce: 1, + balance: U256::from(10), + code_hash: KECCAK_EMPTY, + code: None, + })), + ) + .revert_storage(0, account1(), vec![(slot1(), U256::from(10))]) + .build() + } + + fn sanity_path(bundle1: BundleState, bundle2: BundleState) { + let mut extended = bundle1.clone(); + extended.extend(bundle2.clone()); + + let mut reverted = extended.clone(); + // revert zero does nothing. + reverted.revert(0); + assert_eq!(reverted, extended); + + // revert by one gives us bundle one. + reverted.revert(1); + assert_eq!(reverted, bundle1); + + // reverted by additional one gives us empty bundle. + reverted.revert(1); + assert_eq!(reverted, BundleState::default()); + + let mut reverted = extended.clone(); + + // reverted by bigger number gives us empty bundle + reverted.revert(10); + assert_eq!(reverted, BundleState::default()); + } + + #[test] + fn extend_on_destroyed_values() { + let base_bundle1 = test_bundle1(); + let base_bundle2 = test_bundle2(); + + // test1 + // bundle1 has Destroyed + // bundle2 has Changed + // end should be DestroyedChanged. + let mut b1 = base_bundle1.clone(); + let mut b2 = base_bundle2.clone(); + b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed; + b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed; + b1.extend(b2); + assert_eq!( + b1.state.get_mut(&account1()).unwrap().status, + AccountStatus::DestroyedChanged + ); + + // test2 + // bundle1 has Changed + // bundle2 has Destroyed + // end should be Destroyed + let mut b1 = base_bundle1.clone(); + let mut b2 = base_bundle2.clone(); + b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed; + b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed; + b2.reverts[0][0].1.wipe_storage = true; + b1.extend(b2); + assert_eq!( + b1.state.get_mut(&account1()).unwrap().status, + AccountStatus::Destroyed + ); + + // test2 extension + // revert of b2 should contains plain state of b1. + let mut revert1 = base_bundle2.reverts[0][0].clone(); + revert1.1.wipe_storage = true; + revert1 + .1 + .storage + .insert(slot2(), RevertToSlot::Some(U256::from(15))); + + assert_eq!( + b1.reverts.as_ref(), + vec![base_bundle1.reverts[0].clone(), vec![revert1]], + ); + + // test3 + // bundle1 has InMemoryChange + // bundle2 has Change + // end should be InMemoryChange. + + let mut b1 = base_bundle1.clone(); + let mut b2 = base_bundle2.clone(); + b1.state.get_mut(&account1()).unwrap().status = AccountStatus::InMemoryChange; + b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed; + b1.extend(b2); + assert_eq!( + b1.state.get_mut(&account1()).unwrap().status, + AccountStatus::InMemoryChange + ); + } + + #[test] + fn test_sanity_path() { + sanity_path(test_bundle1(), test_bundle2()); + sanity_path(test_bundle3(), test_bundle4()); + } + + #[test] + fn test_multi_reverts_with_delete() { + let mut state = BundleBuilder::new(0..=3) + .revert_address(0, account1()) + .revert_account_info(2, account1(), Some(Some(AccountInfo::default()))) + .revert_account_info(3, account1(), Some(None)) + .build(); + + state.revert_latest(); + // state for account one was deleted + assert_eq!(state.state.get(&account1()), None); + + state.revert_latest(); + // state is set to + assert_eq!( + state.state.get(&account1()), + Some(&BundleAccount::new( + None, + Some(AccountInfo::default()), + HashMap::new(), + AccountStatus::Changed + )) + ); + } + + #[test] + fn test_revert_capacity() { + let state = BundleState::builder(0..=3) + .revert_address(0, account1()) + .revert_address(2, account2()) + .revert_account_info(0, account1(), Some(None)) + .revert_account_info(2, account2(), None) + .revert_storage(0, account1(), vec![(slot1(), U256::from(10))]) + .build(); + + assert_eq!(state.reverts.len(), 4); + assert_eq!(state.reverts[1], vec![]); + assert_eq!(state.reverts[3], vec![]); + assert_eq!(state.reverts[0].len(), 1); + assert_eq!(state.reverts[2].len(), 1); + + let (addr1, revert1) = &state.reverts[0][0]; + assert_eq!(addr1, &account1()); + assert_eq!(revert1.account, AccountInfoRevert::DeleteIt); + + let (addr2, revert2) = &state.reverts[2][0]; + assert_eq!(addr2, &account2()); + assert_eq!(revert2.account, AccountInfoRevert::DoNothing); + } + + #[test] + fn take_reverts() { + let bundle1 = test_bundle1(); + let bundle2 = test_bundle2(); + + let mut extended = bundle1.clone(); + extended.extend(bundle2.clone()); + + // check that we have two reverts + assert_eq!(extended.reverts.len(), 2); + + // take all by big N + let mut extended2 = extended.clone(); + assert_eq!(extended2.take_n_reverts(100), extended.reverts); + + // take all reverts + let mut extended2 = extended.clone(); + assert_eq!(extended2.take_all_reverts(), extended.reverts); + + // take zero revert + let taken_reverts = extended.take_n_reverts(0); + assert_eq!(taken_reverts, Reverts::default()); + assert_eq!(extended.reverts.len(), 2); + + // take one revert + let taken_reverts = extended.take_n_reverts(1); + assert_eq!(taken_reverts, bundle1.reverts); + + // take last revert + let taken_reverts = extended.take_n_reverts(1); + assert_eq!(taken_reverts, bundle2.reverts); + } + + #[test] + fn prepend_state() { + let address1 = account1(); + let address2 = account2(); + + let account1 = AccountInfo { + nonce: 1, + ..Default::default() + }; + let account1_changed = AccountInfo { + nonce: 1, + ..Default::default() + }; + let account2 = AccountInfo { + nonce: 1, + ..Default::default() + }; + + let present_state = BundleState::builder(2..=2) + .state_present_account_info(address1, account1_changed.clone()) + .build(); + assert_eq!(present_state.reverts.len(), 1); + let previous_state = BundleState::builder(1..=1) + .state_present_account_info(address1, account1) + .state_present_account_info(address2, account2.clone()) + .build(); + assert_eq!(previous_state.reverts.len(), 1); + + let mut test = present_state; + + test.prepend_state(previous_state); + + assert_eq!(test.state.len(), 2); + // reverts num should stay the same. + assert_eq!(test.reverts.len(), 1); + // account1 is not overwritten. + assert_eq!( + test.state.get(&address1).unwrap().info, + Some(account1_changed) + ); + // account2 got inserted + assert_eq!(test.state.get(&address2).unwrap().info, Some(account2)); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/cache.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/cache.md new file mode 100644 index 00000000..17c34a36 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/cache.md @@ -0,0 +1,159 @@ +# ๐Ÿฆ€ cache.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/cache.rs) + +```rust +use super::{ + plain_account::PlainStorage, transition_account::TransitionAccount, CacheAccount, PlainAccount, +}; +use revm_interpreter::primitives::{ + Account, AccountInfo, Address, Bytecode, HashMap, State as EVMState, B256, +}; +use std::vec::Vec; + +/// Cache state contains both modified and original values. +/// +/// Cache state is main state that revm uses to access state. +/// It loads all accounts from database and applies revm output to it. +/// +/// It generates transitions that is used to build BundleState. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct CacheState { + /// Block state account with account state + pub accounts: HashMap, + /// created contracts + /// TODO add bytecode counter for number of bytecodes added/removed. + pub contracts: HashMap, + /// Has EIP-161 state clear enabled (Spurious Dragon hardfork). + pub has_state_clear: bool, +} + +impl Default for CacheState { + fn default() -> Self { + Self::new(true) + } +} + +impl CacheState { + /// New default state. + pub fn new(has_state_clear: bool) -> Self { + Self { + accounts: HashMap::default(), + contracts: HashMap::default(), + has_state_clear, + } + } + + /// Set state clear flag. EIP-161. + pub fn set_state_clear_flag(&mut self, has_state_clear: bool) { + self.has_state_clear = has_state_clear; + } + + /// Helper function that returns all accounts. + /// + /// Used inside tests to generate merkle tree. + pub fn trie_account(&self) -> impl IntoIterator { + self.accounts.iter().filter_map(|(address, account)| { + account + .account + .as_ref() + .map(|plain_acc| (*address, plain_acc)) + }) + } + + /// Insert not existing account. + pub fn insert_not_existing(&mut self, address: Address) { + self.accounts + .insert(address, CacheAccount::new_loaded_not_existing()); + } + + /// Insert Loaded (Or LoadedEmptyEip161 if account is empty) account. + pub fn insert_account(&mut self, address: Address, info: AccountInfo) { + let account = if !info.is_empty() { + CacheAccount::new_loaded(info, HashMap::default()) + } else { + CacheAccount::new_loaded_empty_eip161(HashMap::default()) + }; + self.accounts.insert(address, account); + } + + /// Similar to `insert_account` but with storage. + pub fn insert_account_with_storage( + &mut self, + address: Address, + info: AccountInfo, + storage: PlainStorage, + ) { + let account = if !info.is_empty() { + CacheAccount::new_loaded(info, storage) + } else { + CacheAccount::new_loaded_empty_eip161(storage) + }; + self.accounts.insert(address, account); + } + + /// Apply output of revm execution and create account transitions that are used to build BundleState. + pub fn apply_evm_state(&mut self, evm_state: EVMState) -> Vec<(Address, TransitionAccount)> { + let mut transitions = Vec::with_capacity(evm_state.len()); + for (address, account) in evm_state { + if let Some(transition) = self.apply_account_state(address, account) { + transitions.push((address, transition)); + } + } + transitions + } + + /// Apply updated account state to the cached account. + /// Returns account transition if applicable. + fn apply_account_state( + &mut self, + address: Address, + account: Account, + ) -> Option { + // not touched account are never changed. + if !account.is_touched() { + return None; + } + + let this_account = self + .accounts + .get_mut(&address) + .expect("All accounts should be present inside cache"); + + // If it is marked as selfdestructed inside revm + // we need to changed state to destroyed. + if account.is_selfdestructed() { + return this_account.selfdestruct(); + } + + // Note: it can happen that created contract get selfdestructed in same block + // that is why is_created is checked after selfdestructed + // + // Note: Create2 opcode (Petersburg) was after state clear EIP (Spurious Dragon) + // + // Note: It is possibility to create KECCAK_EMPTY contract with some storage + // by just setting storage inside CRATE constructor. Overlap of those contracts + // is not possible because CREATE2 is introduced later. + if account.is_created() { + return Some(this_account.newly_created(account.info, account.storage)); + } + + // Account is touched, but not selfdestructed or newly created. + // Account can be touched and not changed. + // And when empty account is touched it needs to be removed from database. + // EIP-161 state clear + if account.is_empty() { + if self.has_state_clear { + // touch empty account. + this_account.touch_empty_eip161() + } else { + // if account is empty and state clear is not enabled we should save + // empty account. + this_account.touch_create_pre_eip161(account.storage) + } + } else { + Some(this_account.change(account.info, account.storage)) + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/cache_account.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/cache_account.md new file mode 100644 index 00000000..f986d5bd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/cache_account.md @@ -0,0 +1,320 @@ +# ๐Ÿฆ€ cache_account.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/cache_account.rs) + +```rust +use super::{ + plain_account::PlainStorage, AccountStatus, BundleAccount, PlainAccount, + StorageWithOriginalValues, TransitionAccount, +}; +use revm_interpreter::primitives::{AccountInfo, U256}; +use revm_precompile::HashMap; + +/// Cache account contains plain state that gets updated +/// at every transaction when evm output is applied to CacheState. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct CacheAccount { + pub account: Option, + pub status: AccountStatus, +} + +impl From for CacheAccount { + fn from(account: BundleAccount) -> Self { + let storage = account + .storage + .iter() + .map(|(k, v)| (*k, v.present_value)) + .collect(); + let plain_account = account + .account_info() + .map(|info| PlainAccount { info, storage }); + Self { + account: plain_account, + status: account.status, + } + } +} + +impl CacheAccount { + /// Create new account that is loaded from database. + pub fn new_loaded(info: AccountInfo, storage: PlainStorage) -> Self { + Self { + account: Some(PlainAccount { info, storage }), + status: AccountStatus::Loaded, + } + } + + /// Create new account that is loaded empty from database. + pub fn new_loaded_empty_eip161(storage: PlainStorage) -> Self { + Self { + account: Some(PlainAccount::new_empty_with_storage(storage)), + status: AccountStatus::LoadedEmptyEIP161, + } + } + + /// Loaded not existing account. + pub fn new_loaded_not_existing() -> Self { + Self { + account: None, + status: AccountStatus::LoadedNotExisting, + } + } + + /// Create new account that is newly created + pub fn new_newly_created(info: AccountInfo, storage: PlainStorage) -> Self { + Self { + account: Some(PlainAccount { info, storage }), + status: AccountStatus::InMemoryChange, + } + } + + /// Create account that is destroyed. + pub fn new_destroyed() -> Self { + Self { + account: None, + status: AccountStatus::Destroyed, + } + } + + /// Create changed account + pub fn new_changed(info: AccountInfo, storage: PlainStorage) -> Self { + Self { + account: Some(PlainAccount { info, storage }), + status: AccountStatus::Changed, + } + } + + /// Return true if account is some + pub fn is_some(&self) -> bool { + matches!( + self.status, + AccountStatus::Changed + | AccountStatus::InMemoryChange + | AccountStatus::DestroyedChanged + | AccountStatus::Loaded + | AccountStatus::LoadedEmptyEIP161 + ) + } + + /// Return storage slot if it exist. + pub fn storage_slot(&self, slot: U256) -> Option { + self.account + .as_ref() + .and_then(|a| a.storage.get(&slot).cloned()) + } + + /// Fetch account info if it exist. + pub fn account_info(&self) -> Option { + self.account.as_ref().map(|a| a.info.clone()) + } + + /// Dissolve account into components. + pub fn into_components(self) -> (Option<(AccountInfo, PlainStorage)>, AccountStatus) { + (self.account.map(|a| a.into_components()), self.status) + } + + /// Account got touched and before EIP161 state clear this account is considered created. + pub fn touch_create_pre_eip161( + &mut self, + storage: StorageWithOriginalValues, + ) -> Option { + let previous_status = self.status; + + let had_no_info = self + .account + .as_ref() + .map(|a| a.info.is_empty()) + .unwrap_or_default(); + self.status = self.status.on_touched_created_pre_eip161(had_no_info)?; + + let plain_storage = storage.iter().map(|(k, v)| (*k, v.present_value)).collect(); + let previous_info = self.account.take().map(|a| a.info); + + self.account = Some(PlainAccount::new_empty_with_storage(plain_storage)); + + Some(TransitionAccount { + info: Some(AccountInfo::default()), + status: self.status, + previous_info, + previous_status, + storage, + storage_was_destroyed: false, + }) + } + + /// Touch empty account, related to EIP-161 state clear. + /// + /// This account returns the Transition that is used to create the BundleState. + pub fn touch_empty_eip161(&mut self) -> Option { + let previous_status = self.status; + + // Set account to None. + let previous_info = self.account.take().map(|acc| acc.info); + + // Set account state to Destroyed as we need to clear the storage if it exist. + self.status = self.status.on_touched_empty_post_eip161(); + + if matches!( + previous_status, + AccountStatus::LoadedNotExisting + | AccountStatus::Destroyed + | AccountStatus::DestroyedAgain + ) { + None + } else { + Some(TransitionAccount { + info: None, + status: self.status, + previous_info, + previous_status, + storage: HashMap::default(), + storage_was_destroyed: true, + }) + } + } + + /// Consume self and make account as destroyed. + /// + /// Set account as None and set status to Destroyer or DestroyedAgain. + pub fn selfdestruct(&mut self) -> Option { + // account should be None after selfdestruct so we can take it. + let previous_info = self.account.take().map(|a| a.info); + let previous_status = self.status; + + self.status = self.status.on_selfdestructed(); + + if previous_status == AccountStatus::LoadedNotExisting { + None + } else { + Some(TransitionAccount { + info: None, + status: self.status, + previous_info, + previous_status, + storage: HashMap::new(), + storage_was_destroyed: true, + }) + } + } + + /// Newly created account. + pub fn newly_created( + &mut self, + new_info: AccountInfo, + new_storage: StorageWithOriginalValues, + ) -> TransitionAccount { + let previous_status = self.status; + let previous_info = self.account.take().map(|a| a.info); + + let new_bundle_storage = new_storage + .iter() + .map(|(k, s)| (*k, s.present_value)) + .collect(); + + self.status = self.status.on_created(); + let transition_account = TransitionAccount { + info: Some(new_info.clone()), + status: self.status, + previous_status, + previous_info, + storage: new_storage, + storage_was_destroyed: false, + }; + self.account = Some(PlainAccount { + info: new_info, + storage: new_bundle_storage, + }); + transition_account + } + + /// Increment balance by `balance` amount. Assume that balance will not + /// overflow or be zero. + /// + /// Note: only if balance is zero we would return None as no transition would be made. + pub fn increment_balance(&mut self, balance: u128) -> Option { + if balance == 0 { + return None; + } + let (_, transition) = self.account_info_change(|info| { + info.balance = info.balance.saturating_add(U256::from(balance)); + }); + Some(transition) + } + + fn account_info_change T>( + &mut self, + change: F, + ) -> (T, TransitionAccount) { + let previous_status = self.status; + let previous_info = self.account_info(); + let mut account = self.account.take().unwrap_or_default(); + let output = change(&mut account.info); + self.account = Some(account); + + let had_no_nonce_and_code = previous_info + .as_ref() + .map(AccountInfo::has_no_code_and_nonce) + .unwrap_or_default(); + self.status = self.status.on_changed(had_no_nonce_and_code); + + ( + output, + TransitionAccount { + info: self.account_info(), + status: self.status, + previous_info, + previous_status, + storage: HashMap::new(), + storage_was_destroyed: false, + }, + ) + } + + /// Drain balance from account and return drained amount and transition. + /// + /// Used for DAO hardfork transition. + pub fn drain_balance(&mut self) -> (u128, TransitionAccount) { + self.account_info_change(|info| { + let output = info.balance; + info.balance = U256::ZERO; + output.try_into().unwrap() + }) + } + + pub fn change( + &mut self, + new: AccountInfo, + storage: StorageWithOriginalValues, + ) -> TransitionAccount { + let previous_status = self.status; + let previous_info = self.account.as_ref().map(|a| a.info.clone()); + let mut this_storage = self + .account + .take() + .map(|acc| acc.storage) + .unwrap_or_default(); + + this_storage.extend(storage.iter().map(|(k, s)| (*k, s.present_value))); + let changed_account = PlainAccount { + info: new, + storage: this_storage, + }; + + let had_no_nonce_and_code = previous_info + .as_ref() + .map(AccountInfo::has_no_code_and_nonce) + .unwrap_or_default(); + self.status = self.status.on_changed(had_no_nonce_and_code); + self.account = Some(changed_account); + + TransitionAccount { + info: self.account.as_ref().map(|a| a.info.clone()), + status: self.status, + previous_info, + previous_status, + storage, + storage_was_destroyed: false, + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/changes.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/changes.md new file mode 100644 index 00000000..5d069ffc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/changes.md @@ -0,0 +1,77 @@ +# ๐Ÿฆ€ changes.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/changes.rs) + +```rust +use super::RevertToSlot; +use revm_interpreter::primitives::{AccountInfo, Address, Bytecode, B256, U256}; +use std::vec::Vec; + +/// accounts/storages/contracts for inclusion into database. +/// Structure is made so it is easier to apply directly to database +/// that mostly have separate tables to store account/storage/contract data. +/// +/// Note: that data is **not** sorted. Some database benefit of faster inclusion +/// and smaller footprint if data is inserted in sorted order. +#[derive(Clone, Debug, Default)] +pub struct StateChangeset { + /// Vector of **not** sorted accounts information. + pub accounts: Vec<(Address, Option)>, + /// Vector of **not** sorted storage. + pub storage: Vec, + /// Vector of contracts by bytecode hash. **not** sorted. + pub contracts: Vec<(B256, Bytecode)>, +} + +/// Plain storage changeset. Used to apply storage changes of plain state to +/// the database. +#[derive(Clone, Debug, PartialEq, Eq, Default)] +pub struct PlainStorageChangeset { + /// Address of account + pub address: Address, + /// Wipe storage, + pub wipe_storage: bool, + /// Storage key value pairs. + pub storage: Vec<(U256, U256)>, +} + +/// Plain Storage Revert. Containing old values of changed storage. +#[derive(Clone, Debug, PartialEq, Eq, Default)] +pub struct PlainStorageRevert { + /// Address of account + pub address: Address, + /// Is storage wiped in this revert. Wiped flag is set on + /// first known selfdestruct and would require clearing the + /// state of this storage from database (And moving it to revert). + pub wiped: bool, + /// Contains the storage key and old values of that storage. + /// Reverts are **not** sorted. + pub storage_revert: Vec<(U256, RevertToSlot)>, +} + +/// Plain state reverts are used to easily store reverts into database. +/// +/// Note that accounts are assumed **not** sorted. +#[derive(Clone, Debug, Default)] +pub struct PlainStateReverts { + /// Vector of account with removed contracts bytecode + /// + /// Note: If AccountInfo is None means that account needs to be removed. + pub accounts: Vec)>>, + /// Vector of storage with its address. + pub storage: Vec>, +} + +impl PlainStateReverts { + /// Constructs new [PlainStateReverts] with pre-allocated capacity. + pub fn with_capacity(capacity: usize) -> Self { + Self { + accounts: Vec::with_capacity(capacity), + storage: Vec::with_capacity(capacity), + } + } +} + +/// Storage reverts +pub type StorageRevert = Vec)>>; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/plain_account.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/plain_account.md new file mode 100644 index 00000000..ace29ef2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/plain_account.md @@ -0,0 +1,45 @@ +# ๐Ÿฆ€ plain_account.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/plain_account.rs) + +```rust +use revm_interpreter::primitives::{AccountInfo, HashMap, StorageSlot, U256}; + +// TODO rename this to BundleAccount. As for the block level we have original state. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct PlainAccount { + pub info: AccountInfo, + pub storage: PlainStorage, +} + +impl PlainAccount { + pub fn new_empty_with_storage(storage: PlainStorage) -> Self { + Self { + info: AccountInfo::default(), + storage, + } + } + + pub fn into_components(self) -> (AccountInfo, PlainStorage) { + (self.info, self.storage) + } +} + +/// This storage represent values that are before block changed. +/// +/// Note: Storage that we get EVM contains original values before t +pub type StorageWithOriginalValues = HashMap; + +/// Simple plain storage that does not have previous value. +/// This is used for loading from database, cache and for bundle state. +pub type PlainStorage = HashMap; + +impl From for PlainAccount { + fn from(info: AccountInfo) -> Self { + Self { + info, + storage: HashMap::new(), + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/reverts.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/reverts.md new file mode 100644 index 00000000..b1ab6af1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/reverts.md @@ -0,0 +1,221 @@ +# ๐Ÿฆ€ reverts.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/reverts.rs) + +```rust +use super::{ + changes::PlainStorageRevert, AccountStatus, BundleAccount, PlainStateReverts, + StorageWithOriginalValues, +}; +use core::ops::{Deref, DerefMut}; +use revm_interpreter::primitives::{AccountInfo, Address, HashMap, U256}; +use std::vec::Vec; + +/// Contains reverts of multiple account in multiple transitions (Transitions as a block). +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct Reverts(Vec>); + +impl Deref for Reverts { + type Target = Vec>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Reverts { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Reverts { + /// Create new reverts + pub fn new(reverts: Vec>) -> Self { + Self(reverts) + } + + /// Sort account inside transition by their address. + pub fn sort(&mut self) { + for revert in &mut self.0 { + revert.sort_by_key(|(address, _)| *address); + } + } + + /// Extend reverts with other reverts. + pub fn extend(&mut self, other: Reverts) { + self.0.extend(other.0); + } + + /// Consume reverts and create plain state reverts. + /// + /// Note that account are sorted by address. + pub fn into_plain_state_reverts(mut self) -> PlainStateReverts { + let mut state_reverts = PlainStateReverts::with_capacity(self.0.len()); + for reverts in self.0.drain(..) { + // pessimistically pre-allocate assuming _all_ accounts changed. + let mut accounts = Vec::with_capacity(reverts.len()); + let mut storage = Vec::with_capacity(reverts.len()); + for (address, revert_account) in reverts.into_iter() { + match revert_account.account { + AccountInfoRevert::RevertTo(acc) => accounts.push((address, Some(acc))), + AccountInfoRevert::DeleteIt => accounts.push((address, None)), + AccountInfoRevert::DoNothing => (), + } + if revert_account.wipe_storage || !revert_account.storage.is_empty() { + storage.push(PlainStorageRevert { + address, + wiped: revert_account.wipe_storage, + storage_revert: revert_account.storage.into_iter().collect::>(), + }); + } + } + state_reverts.accounts.push(accounts); + state_reverts.storage.push(storage); + } + state_reverts + } +} + +/// Assumption is that Revert can return full state from any future state to any past state. +/// +/// It is created when new account state is applied to old account state. +/// And it is used to revert new account state to the old account state. +/// +/// AccountRevert is structured in this way as we need to save it inside database. +/// And we need to be able to read it from database. +#[derive(Clone, Default, Debug, PartialEq, Eq)] +pub struct AccountRevert { + pub account: AccountInfoRevert, + pub storage: HashMap, + pub previous_status: AccountStatus, + pub wipe_storage: bool, +} + +impl AccountRevert { + /// The approximate size of changes needed to store this account revert. + /// `1 + storage_reverts_len` + pub fn size_hint(&self) -> usize { + 1 + self.storage.len() + } + + /// Very similar to new_selfdestructed but it will add additional zeros (RevertToSlot::Destroyed) + /// for the storage that are set if account is again created. + pub fn new_selfdestructed_again( + status: AccountStatus, + account: AccountInfoRevert, + mut previous_storage: StorageWithOriginalValues, + updated_storage: StorageWithOriginalValues, + ) -> Self { + // Take present storage values as the storages that we are going to revert to. + // As those values got destroyed. + let mut previous_storage: HashMap = previous_storage + .drain() + .map(|(key, value)| (key, RevertToSlot::Some(value.present_value))) + .collect(); + for (key, _) in updated_storage { + previous_storage + .entry(key) + .or_insert(RevertToSlot::Destroyed); + } + AccountRevert { + account, + storage: previous_storage, + previous_status: status, + wipe_storage: false, + } + } + + /// Create revert for states that were before selfdestruct. + pub fn new_selfdestructed_from_bundle( + account_info_revert: AccountInfoRevert, + bundle_account: &mut BundleAccount, + updated_storage: &StorageWithOriginalValues, + ) -> Option { + match bundle_account.status { + AccountStatus::InMemoryChange + | AccountStatus::Changed + | AccountStatus::LoadedEmptyEIP161 + | AccountStatus::Loaded => { + let mut ret = AccountRevert::new_selfdestructed_again( + bundle_account.status, + account_info_revert, + bundle_account.storage.drain().collect(), + updated_storage.clone(), + ); + ret.wipe_storage = true; + Some(ret) + } + _ => None, + } + } + + /// Create new selfdestruct revert. + pub fn new_selfdestructed( + status: AccountStatus, + account: AccountInfoRevert, + mut storage: StorageWithOriginalValues, + ) -> Self { + // Zero all present storage values and save present values to AccountRevert. + let previous_storage = storage + .iter_mut() + .map(|(key, value)| { + // take previous value and set ZERO as storage got destroyed. + (*key, RevertToSlot::Some(value.present_value)) + }) + .collect(); + + Self { + account, + storage: previous_storage, + previous_status: status, + wipe_storage: true, + } + } + + /// Returns `true` if there is nothing to revert, + /// by checking that: + /// * both account info and storage have been left untouched + /// * we don't need to wipe storage + pub fn is_empty(&self) -> bool { + self.account == AccountInfoRevert::DoNothing + && self.storage.is_empty() + && !self.wipe_storage + } +} + +/// Depending on previous state of account info this +/// will tell us what to do on revert. +#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] +pub enum AccountInfoRevert { + #[default] + /// Nothing changed + DoNothing, + /// Account was created and on revert we need to remove it with all storage. + DeleteIt, + /// Account was changed and on revert we need to put old state. + RevertTo(AccountInfo), +} + +/// So storage can have multiple types: +/// * Zero, on revert remove plain state. +/// * Value, on revert set this value +/// * Destroyed, should be removed on revert but on Revert set it as zero. +/// +/// Note: It is completely different state if Storage is Zero or Some or if Storage was +/// Destroyed. Because if it is destroyed, previous values can be found in database or it can be zero. +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash)] +pub enum RevertToSlot { + Some(U256), + Destroyed, +} + +impl RevertToSlot { + pub fn to_previous_value(self) -> U256 { + match self { + RevertToSlot::Some(value) => value, + RevertToSlot::Destroyed => U256::ZERO, + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/state.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/state.md new file mode 100644 index 00000000..63b04847 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/state.md @@ -0,0 +1,799 @@ +# ๐Ÿฆ€ state.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/state.rs) + +```rust +use super::{ + bundle_state::BundleRetention, cache::CacheState, plain_account::PlainStorage, BundleState, + CacheAccount, StateBuilder, TransitionAccount, TransitionState, +}; +use crate::db::EmptyDB; +use revm_interpreter::primitives::{ + db::{Database, DatabaseCommit}, + hash_map, Account, AccountInfo, Address, Bytecode, HashMap, B256, BLOCK_HASH_HISTORY, U256, +}; +use std::{ + boxed::Box, + collections::{btree_map, BTreeMap}, + vec::Vec, +}; + +/// Database boxed with a lifetime and Send. +pub type DBBox<'a, E> = Box + Send + 'a>; + +/// More constrained version of State that uses Boxed database with a lifetime. +/// +/// This is used to make it easier to use State. +pub type StateDBBox<'a, E> = State>; + +/// State of blockchain. +/// +/// State clear flag is set inside CacheState and by default it is enabled. +/// If you want to disable it use `set_state_clear_flag` function. +#[derive(Debug)] +pub struct State { + /// Cached state contains both changed from evm execution and cached/loaded account/storages + /// from database. This allows us to have only one layer of cache where we can fetch data. + /// Additionally we can introduce some preloading of data from database. + pub cache: CacheState, + /// Optional database that we use to fetch data from. If database is not present, we will + /// return not existing account and storage. + /// + /// Note: It is marked as Send so database can be shared between threads. + pub database: DB, + /// Block state, it aggregates transactions transitions into one state. + /// + /// Build reverts and state that gets applied to the state. + pub transition_state: Option, + /// After block is finishes we merge those changes inside bundle. + /// Bundle is used to update database and create changesets. + /// Bundle state can be set on initialization if we want to use preloaded bundle. + pub bundle_state: BundleState, + /// Addition layer that is going to be used to fetched values before fetching values + /// from database. + /// + /// Bundle is the main output of the state execution and this allows setting previous bundle + /// and using its values for execution. + pub use_preloaded_bundle: bool, + /// If EVM asks for block hash we will first check if they are found here. + /// and then ask the database. + /// + /// This map can be used to give different values for block hashes if in case + /// The fork block is different or some blocks are not saved inside database. + pub block_hashes: BTreeMap, +} + +// Have ability to call State::builder without having to specify the type. +impl State { + /// Return the builder that build the State. + pub fn builder() -> StateBuilder { + StateBuilder::default() + } +} + +impl State { + /// Returns the size hint for the inner bundle state. + /// See [BundleState::size_hint] for more info. + pub fn bundle_size_hint(&self) -> usize { + self.bundle_state.size_hint() + } + + /// Iterate over received balances and increment all account balances. + /// If account is not found inside cache state it will be loaded from database. + /// + /// Update will create transitions for all accounts that are updated. + /// + /// Like [CacheAccount::increment_balance], this assumes that incremented balances are not + /// zero, and will not overflow once incremented. If using this to implement withdrawals, zero + /// balances must be filtered out before calling this function. + pub fn increment_balances( + &mut self, + balances: impl IntoIterator, + ) -> Result<(), DB::Error> { + // make transition and update cache state + let mut transitions = Vec::new(); + for (address, balance) in balances { + if balance == 0 { + continue; + } + let original_account = self.load_cache_account(address)?; + transitions.push(( + address, + original_account + .increment_balance(balance) + .expect("Balance is not zero"), + )) + } + // append transition + if let Some(s) = self.transition_state.as_mut() { + s.add_transitions(transitions) + } + Ok(()) + } + + /// Drain balances from given account and return those values. + /// + /// It is used for DAO hardfork state change to move values from given accounts. + pub fn drain_balances( + &mut self, + addresses: impl IntoIterator, + ) -> Result, DB::Error> { + // make transition and update cache state + let mut transitions = Vec::new(); + let mut balances = Vec::new(); + for address in addresses { + let original_account = self.load_cache_account(address)?; + let (balance, transition) = original_account.drain_balance(); + balances.push(balance); + transitions.push((address, transition)) + } + // append transition + if let Some(s) = self.transition_state.as_mut() { + s.add_transitions(transitions) + } + Ok(balances) + } + + /// State clear EIP-161 is enabled in Spurious Dragon hardfork. + pub fn set_state_clear_flag(&mut self, has_state_clear: bool) { + self.cache.set_state_clear_flag(has_state_clear); + } + + pub fn insert_not_existing(&mut self, address: Address) { + self.cache.insert_not_existing(address) + } + + pub fn insert_account(&mut self, address: Address, info: AccountInfo) { + self.cache.insert_account(address, info) + } + + pub fn insert_account_with_storage( + &mut self, + address: Address, + info: AccountInfo, + storage: PlainStorage, + ) { + self.cache + .insert_account_with_storage(address, info, storage) + } + + /// Apply evm transitions to transition state. + pub fn apply_transition(&mut self, transitions: Vec<(Address, TransitionAccount)>) { + // add transition to transition state. + if let Some(s) = self.transition_state.as_mut() { + s.add_transitions(transitions) + } + } + + /// Take all transitions and merge them inside bundle state. + /// This action will create final post state and all reverts so that + /// we at any time revert state of bundle to the state before transition + /// is applied. + pub fn merge_transitions(&mut self, retention: BundleRetention) { + if let Some(transition_state) = self.transition_state.as_mut().map(TransitionState::take) { + self.bundle_state + .apply_transitions_and_create_reverts(transition_state, retention); + } + } + + pub fn load_cache_account(&mut self, address: Address) -> Result<&mut CacheAccount, DB::Error> { + match self.cache.accounts.entry(address) { + hash_map::Entry::Vacant(entry) => { + if self.use_preloaded_bundle { + // load account from bundle state + if let Some(account) = + self.bundle_state.account(&address).cloned().map(Into::into) + { + return Ok(entry.insert(account)); + } + } + // if not found in bundle, load it from database + let info = self.database.basic(address)?; + let account = match info { + None => CacheAccount::new_loaded_not_existing(), + Some(acc) if acc.is_empty() => { + CacheAccount::new_loaded_empty_eip161(HashMap::new()) + } + Some(acc) => CacheAccount::new_loaded(acc, HashMap::new()), + }; + Ok(entry.insert(account)) + } + hash_map::Entry::Occupied(entry) => Ok(entry.into_mut()), + } + } + + // TODO make cache aware of transitions dropping by having global transition counter. + /// Takes changeset and reverts from state and replaces it with empty one. + /// This will trop pending Transition and any transitions would be lost. + /// + /// NOTE: If either: + /// * The [State] has not been built with [StateBuilder::with_bundle_update], or + /// * The [State] has a [TransitionState] set to `None` when + /// [State::merge_transitions] is called, + /// + /// this will panic. + pub fn take_bundle(&mut self) -> BundleState { + core::mem::take(&mut self.bundle_state) + } +} + +impl Database for State { + type Error = DB::Error; + + fn basic(&mut self, address: Address) -> Result, Self::Error> { + self.load_cache_account(address).map(|a| a.account_info()) + } + + fn code_by_hash(&mut self, code_hash: B256) -> Result { + let res = match self.cache.contracts.entry(code_hash) { + hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()), + hash_map::Entry::Vacant(entry) => { + if self.use_preloaded_bundle { + if let Some(code) = self.bundle_state.contracts.get(&code_hash) { + entry.insert(code.clone()); + return Ok(code.clone()); + } + } + // if not found in bundle ask database + let code = self.database.code_by_hash(code_hash)?; + entry.insert(code.clone()); + Ok(code) + } + }; + res + } + + fn storage(&mut self, address: Address, index: U256) -> Result { + // Account is guaranteed to be loaded. + // Note that storage from bundle is already loaded with account. + if let Some(account) = self.cache.accounts.get_mut(&address) { + // account will always be some, but if it is not, U256::ZERO will be returned. + let is_storage_known = account.status.is_storage_known(); + Ok(account + .account + .as_mut() + .map(|account| match account.storage.entry(index) { + hash_map::Entry::Occupied(entry) => Ok(*entry.get()), + hash_map::Entry::Vacant(entry) => { + // if account was destroyed or account is newly built + // we return zero and don't ask database. + let value = if is_storage_known { + U256::ZERO + } else { + self.database.storage(address, index)? + }; + entry.insert(value); + Ok(value) + } + }) + .transpose()? + .unwrap_or_default()) + } else { + unreachable!("For accessing any storage account is guaranteed to be loaded beforehand") + } + } + + fn block_hash(&mut self, number: U256) -> Result { + // block number is never bigger then u64::MAX. + let u64num: u64 = number.to(); + match self.block_hashes.entry(u64num) { + btree_map::Entry::Occupied(entry) => Ok(*entry.get()), + btree_map::Entry::Vacant(entry) => { + let ret = *entry.insert(self.database.block_hash(number)?); + + // prune all hashes that are older then BLOCK_HASH_HISTORY + while let Some(entry) = self.block_hashes.first_entry() { + if *entry.key() < u64num.saturating_sub(BLOCK_HASH_HISTORY as u64) { + entry.remove(); + } else { + break; + } + } + + Ok(ret) + } + } + } +} + +impl DatabaseCommit for State { + fn commit(&mut self, evm_state: HashMap) { + let transitions = self.cache.apply_evm_state(evm_state); + self.apply_transition(transitions); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::db::{ + states::reverts::AccountInfoRevert, AccountRevert, AccountStatus, BundleAccount, + RevertToSlot, + }; + use revm_interpreter::primitives::{keccak256, StorageSlot}; + + #[test] + fn block_hash_cache() { + let mut state = State::builder().build(); + state.block_hash(U256::from(1)).unwrap(); + state.block_hash(U256::from(2)).unwrap(); + + let test_number = BLOCK_HASH_HISTORY as u64 + 2; + + let block1_hash = keccak256(U256::from(1).to_string().as_bytes()); + let block2_hash = keccak256(U256::from(2).to_string().as_bytes()); + let block_test_hash = keccak256(U256::from(test_number).to_string().as_bytes()); + + assert_eq!( + state.block_hashes, + BTreeMap::from([(1, block1_hash), (2, block2_hash)]) + ); + + state.block_hash(U256::from(test_number)).unwrap(); + assert_eq!( + state.block_hashes, + BTreeMap::from([(test_number, block_test_hash), (2, block2_hash)]) + ); + } + + /// Checks that if accounts is touched multiple times in the same block, + /// then the old values from the first change are preserved and not overwritten. + /// + /// This is important because the state transitions from different transactions in the same block may see + /// different states of the same account as the old value, but the revert should reflect the + /// state of the account before the block. + #[test] + fn reverts_preserve_old_values() { + let mut state = State::builder().with_bundle_update().build(); + + let (slot1, slot2, slot3) = (U256::from(1), U256::from(2), U256::from(3)); + + // Non-existing account for testing account state transitions. + // [LoadedNotExisting] -> [Changed] (nonce: 1, balance: 1) -> [Changed] (nonce: 2) -> [Changed] (nonce: 3) + let new_account_address = Address::from_slice(&[0x1; 20]); + let new_account_created_info = AccountInfo { + nonce: 1, + balance: U256::from(1), + ..Default::default() + }; + let new_account_changed_info = AccountInfo { + nonce: 2, + ..new_account_created_info.clone() + }; + let new_account_changed_info2 = AccountInfo { + nonce: 3, + ..new_account_changed_info.clone() + }; + + // Existing account for testing storage state transitions. + let existing_account_address = Address::from_slice(&[0x2; 20]); + let existing_account_initial_info = AccountInfo { + nonce: 1, + ..Default::default() + }; + let existing_account_initial_storage = HashMap::::from([ + (slot1, U256::from(100)), // 0x01 => 100 + (slot2, U256::from(200)), // 0x02 => 200 + ]); + let existing_account_changed_info = AccountInfo { + nonce: 2, + ..existing_account_initial_info.clone() + }; + + // A transaction in block 1 creates one account and changes an existing one. + state.apply_transition(Vec::from([ + ( + new_account_address, + TransitionAccount { + status: AccountStatus::InMemoryChange, + info: Some(new_account_created_info.clone()), + previous_status: AccountStatus::LoadedNotExisting, + previous_info: None, + ..Default::default() + }, + ), + ( + existing_account_address, + TransitionAccount { + status: AccountStatus::InMemoryChange, + info: Some(existing_account_changed_info.clone()), + previous_status: AccountStatus::Loaded, + previous_info: Some(existing_account_initial_info.clone()), + storage: HashMap::from([( + slot1, + StorageSlot::new_changed( + *existing_account_initial_storage.get(&slot1).unwrap(), + U256::from(1000), + ), + )]), + storage_was_destroyed: false, + }, + ), + ])); + + // A transaction in block 1 then changes the same account. + state.apply_transition(Vec::from([( + new_account_address, + TransitionAccount { + status: AccountStatus::InMemoryChange, + info: Some(new_account_changed_info.clone()), + previous_status: AccountStatus::InMemoryChange, + previous_info: Some(new_account_created_info.clone()), + ..Default::default() + }, + )])); + + // Another transaction in block 1 then changes the newly created account yet again and modifies the storage in an existing one. + state.apply_transition(Vec::from([ + ( + new_account_address, + TransitionAccount { + status: AccountStatus::InMemoryChange, + info: Some(new_account_changed_info2.clone()), + previous_status: AccountStatus::InMemoryChange, + previous_info: Some(new_account_changed_info), + storage: HashMap::from([( + slot1, + StorageSlot::new_changed(U256::ZERO, U256::from(1)), + )]), + storage_was_destroyed: false, + }, + ), + ( + existing_account_address, + TransitionAccount { + status: AccountStatus::InMemoryChange, + info: Some(existing_account_changed_info.clone()), + previous_status: AccountStatus::InMemoryChange, + previous_info: Some(existing_account_changed_info.clone()), + storage: HashMap::from([ + ( + slot1, + StorageSlot::new_changed(U256::from(100), U256::from(1_000)), + ), + ( + slot2, + StorageSlot::new_changed( + *existing_account_initial_storage.get(&slot2).unwrap(), + U256::from(2_000), + ), + ), + // Create new slot + ( + slot3, + StorageSlot::new_changed(U256::ZERO, U256::from(3_000)), + ), + ]), + storage_was_destroyed: false, + }, + ), + ])); + + state.merge_transitions(BundleRetention::Reverts); + let mut bundle_state = state.take_bundle(); + + // The new account revert should be `DeleteIt` since this was an account creation. + // The existing account revert should be reverted to its previous state. + bundle_state.reverts.sort(); + assert_eq!( + bundle_state.reverts.as_ref(), + Vec::from([Vec::from([ + ( + new_account_address, + AccountRevert { + account: AccountInfoRevert::DeleteIt, + previous_status: AccountStatus::LoadedNotExisting, + storage: HashMap::from([(slot1, RevertToSlot::Some(U256::ZERO))]), + wipe_storage: false, + } + ), + ( + existing_account_address, + AccountRevert { + account: AccountInfoRevert::RevertTo(existing_account_initial_info.clone()), + previous_status: AccountStatus::Loaded, + storage: HashMap::from([ + ( + slot1, + RevertToSlot::Some( + *existing_account_initial_storage.get(&slot1).unwrap() + ) + ), + ( + slot2, + RevertToSlot::Some( + *existing_account_initial_storage.get(&slot2).unwrap() + ) + ), + (slot3, RevertToSlot::Some(U256::ZERO)) + ]), + wipe_storage: false, + } + ), + ])]), + "The account or storage reverts are incorrect" + ); + + // The latest state of the new account should be: nonce = 3, balance = 1, code & code hash = None. + // Storage: 0x01 = 1. + assert_eq!( + bundle_state.account(&new_account_address), + Some(&BundleAccount { + info: Some(new_account_changed_info2), + original_info: None, + status: AccountStatus::InMemoryChange, + storage: HashMap::from([( + slot1, + StorageSlot::new_changed(U256::ZERO, U256::from(1)) + )]), + }), + "The latest state of the new account is incorrect" + ); + + // The latest state of the existing account should be: nonce = 2. + // Storage: 0x01 = 1000, 0x02 = 2000, 0x03 = 3000. + assert_eq!( + bundle_state.account(&existing_account_address), + Some(&BundleAccount { + info: Some(existing_account_changed_info), + original_info: Some(existing_account_initial_info), + status: AccountStatus::InMemoryChange, + storage: HashMap::from([ + ( + slot1, + StorageSlot::new_changed( + *existing_account_initial_storage.get(&slot1).unwrap(), + U256::from(1_000) + ) + ), + ( + slot2, + StorageSlot::new_changed( + *existing_account_initial_storage.get(&slot2).unwrap(), + U256::from(2_000) + ) + ), + // Create new slot + ( + slot3, + StorageSlot::new_changed(U256::ZERO, U256::from(3_000)) + ), + ]), + }), + "The latest state of the existing account is incorrect" + ); + } + + /// Checks that the accounts and storages that are changed within the + /// block and reverted to their previous state do not appear in the reverts. + #[test] + fn bundle_scoped_reverts_collapse() { + let mut state = State::builder().with_bundle_update().build(); + + // Non-existing account. + let new_account_address = Address::from_slice(&[0x1; 20]); + let new_account_created_info = AccountInfo { + nonce: 1, + balance: U256::from(1), + ..Default::default() + }; + + // Existing account. + let existing_account_address = Address::from_slice(&[0x2; 20]); + let existing_account_initial_info = AccountInfo { + nonce: 1, + ..Default::default() + }; + let existing_account_updated_info = AccountInfo { + nonce: 1, + balance: U256::from(1), + ..Default::default() + }; + + // Existing account with storage. + let (slot1, slot2) = (U256::from(1), U256::from(2)); + let existing_account_with_storage_address = Address::from_slice(&[0x3; 20]); + let existing_account_with_storage_info = AccountInfo { + nonce: 1, + ..Default::default() + }; + // A transaction in block 1 creates a new account. + state.apply_transition(Vec::from([ + ( + new_account_address, + TransitionAccount { + status: AccountStatus::InMemoryChange, + info: Some(new_account_created_info.clone()), + previous_status: AccountStatus::LoadedNotExisting, + previous_info: None, + ..Default::default() + }, + ), + ( + existing_account_address, + TransitionAccount { + status: AccountStatus::Changed, + info: Some(existing_account_updated_info.clone()), + previous_status: AccountStatus::Loaded, + previous_info: Some(existing_account_initial_info.clone()), + ..Default::default() + }, + ), + ( + existing_account_with_storage_address, + TransitionAccount { + status: AccountStatus::Changed, + info: Some(existing_account_with_storage_info.clone()), + previous_status: AccountStatus::Loaded, + previous_info: Some(existing_account_with_storage_info.clone()), + storage: HashMap::from([ + ( + slot1, + StorageSlot::new_changed(U256::from(1), U256::from(10)), + ), + (slot2, StorageSlot::new_changed(U256::ZERO, U256::from(20))), + ]), + storage_was_destroyed: false, + }, + ), + ])); + + // Another transaction in block 1 destroys new account. + state.apply_transition(Vec::from([ + ( + new_account_address, + TransitionAccount { + status: AccountStatus::Destroyed, + info: None, + previous_status: AccountStatus::InMemoryChange, + previous_info: Some(new_account_created_info), + ..Default::default() + }, + ), + ( + existing_account_address, + TransitionAccount { + status: AccountStatus::Changed, + info: Some(existing_account_initial_info), + previous_status: AccountStatus::Changed, + previous_info: Some(existing_account_updated_info), + ..Default::default() + }, + ), + ( + existing_account_with_storage_address, + TransitionAccount { + status: AccountStatus::Changed, + info: Some(existing_account_with_storage_info.clone()), + previous_status: AccountStatus::Changed, + previous_info: Some(existing_account_with_storage_info.clone()), + storage: HashMap::from([ + ( + slot1, + StorageSlot::new_changed(U256::from(10), U256::from(1)), + ), + (slot2, StorageSlot::new_changed(U256::from(20), U256::ZERO)), + ]), + storage_was_destroyed: false, + }, + ), + ])); + + state.merge_transitions(BundleRetention::Reverts); + + let mut bundle_state = state.take_bundle(); + bundle_state.reverts.sort(); + + // both account info and storage are left as before transitions, + // therefore there is nothing to revert + assert_eq!(bundle_state.reverts.as_ref(), Vec::from([Vec::from([])])); + } + + /// Checks that the behavior of selfdestruct within the block is correct. + #[test] + fn selfdestruct_state_and_reverts() { + let mut state = State::builder().with_bundle_update().build(); + + // Existing account. + let existing_account_address = Address::from_slice(&[0x1; 20]); + let existing_account_info = AccountInfo { + nonce: 1, + ..Default::default() + }; + + let (slot1, slot2) = (U256::from(1), U256::from(2)); + + // Existing account is destroyed. + state.apply_transition(Vec::from([( + existing_account_address, + TransitionAccount { + status: AccountStatus::Destroyed, + info: None, + previous_status: AccountStatus::Loaded, + previous_info: Some(existing_account_info.clone()), + storage: HashMap::default(), + storage_was_destroyed: true, + }, + )])); + + // Existing account is re-created and slot 0x01 is changed. + state.apply_transition(Vec::from([( + existing_account_address, + TransitionAccount { + status: AccountStatus::DestroyedChanged, + info: Some(existing_account_info.clone()), + previous_status: AccountStatus::Destroyed, + previous_info: None, + storage: HashMap::from([( + slot1, + StorageSlot::new_changed(U256::ZERO, U256::from(1)), + )]), + storage_was_destroyed: false, + }, + )])); + + // Slot 0x01 is changed, but existing account is destroyed again. + state.apply_transition(Vec::from([( + existing_account_address, + TransitionAccount { + status: AccountStatus::DestroyedAgain, + info: None, + previous_status: AccountStatus::DestroyedChanged, + previous_info: Some(existing_account_info.clone()), + // storage change should be ignored + storage: HashMap::default(), + storage_was_destroyed: true, + }, + )])); + + // Existing account is re-created and slot 0x02 is changed. + state.apply_transition(Vec::from([( + existing_account_address, + TransitionAccount { + status: AccountStatus::DestroyedChanged, + info: Some(existing_account_info.clone()), + previous_status: AccountStatus::DestroyedAgain, + previous_info: None, + storage: HashMap::from([( + slot2, + StorageSlot::new_changed(U256::ZERO, U256::from(2)), + )]), + storage_was_destroyed: false, + }, + )])); + + state.merge_transitions(BundleRetention::Reverts); + + let bundle_state = state.take_bundle(); + + assert_eq!( + bundle_state.state, + HashMap::from([( + existing_account_address, + BundleAccount { + info: Some(existing_account_info.clone()), + original_info: Some(existing_account_info.clone()), + storage: HashMap::from([( + slot2, + StorageSlot::new_changed(U256::ZERO, U256::from(2)) + )]), + status: AccountStatus::DestroyedChanged, + } + )]) + ); + + assert_eq!( + bundle_state.reverts.as_ref(), + Vec::from([Vec::from([( + existing_account_address, + AccountRevert { + account: AccountInfoRevert::DoNothing, + previous_status: AccountStatus::Loaded, + storage: HashMap::from([(slot2, RevertToSlot::Destroyed)]), + wipe_storage: true, + } + )])]) + ) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/state_builder.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/state_builder.md new file mode 100644 index 00000000..c2cbdf14 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/state_builder.md @@ -0,0 +1,177 @@ +# ๐Ÿฆ€ state_builder.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/state_builder.rs) + +```rust +use super::{cache::CacheState, state::DBBox, BundleState, State, TransitionState}; +use crate::db::EmptyDB; +use revm_interpreter::primitives::{ + db::{Database, DatabaseRef, WrapDatabaseRef}, + B256, +}; +use std::collections::BTreeMap; + +/// Allows building of State and initializing it with different options. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct StateBuilder { + /// Database that we use to fetch data from. + database: DB, + /// Enabled state clear flag that is introduced in Spurious Dragon hardfork. + /// Default is true as spurious dragon happened long time ago. + with_state_clear: bool, + /// if there is prestate that we want to use. + /// This would mean that we have additional state layer between evm and disk/database. + with_bundle_prestate: Option, + /// This will initialize cache to this state. + with_cache_prestate: Option, + /// Do we want to create reverts and update bundle state. + /// Default is false. + with_bundle_update: bool, + /// Do we want to merge transitions in background. + /// This will allows evm to continue executing. + /// Default is false. + with_background_transition_merge: bool, + /// If we want to set different block hashes + with_block_hashes: BTreeMap, +} + +impl StateBuilder { + /// Create a new builder with an empty database. + /// + /// If you want to instantiate it with a specific database, use + /// [`new_with_database`](Self::new_with_database). + pub fn new() -> Self { + Self::default() + } +} + +impl Default for StateBuilder { + fn default() -> Self { + Self::new_with_database(DB::default()) + } +} + +impl StateBuilder { + /// Create a new builder with the given database. + pub fn new_with_database(database: DB) -> Self { + Self { + database, + with_state_clear: true, + with_cache_prestate: None, + with_bundle_prestate: None, + with_bundle_update: false, + with_background_transition_merge: false, + with_block_hashes: BTreeMap::new(), + } + } + + /// Set the database. + pub fn with_database(self, database: ODB) -> StateBuilder { + // cast to the different database, + // Note that we return different type depending of the database NewDBError. + StateBuilder { + with_state_clear: self.with_state_clear, + database, + with_cache_prestate: self.with_cache_prestate, + with_bundle_prestate: self.with_bundle_prestate, + with_bundle_update: self.with_bundle_update, + with_background_transition_merge: self.with_background_transition_merge, + with_block_hashes: self.with_block_hashes, + } + } + + /// Takes [DatabaseRef] and wraps it with [WrapDatabaseRef]. + pub fn with_database_ref( + self, + database: ODB, + ) -> StateBuilder> { + self.with_database(WrapDatabaseRef(database)) + } + + /// With boxed version of database. + pub fn with_database_boxed( + self, + database: DBBox<'_, Error>, + ) -> StateBuilder> { + self.with_database(database) + } + + /// By default state clear flag is enabled but for initial sync on mainnet + /// we want to disable it so proper consensus changes are in place. + pub fn without_state_clear(self) -> Self { + Self { + with_state_clear: false, + ..self + } + } + + /// Allows setting prestate that is going to be used for execution. + /// This bundle state will act as additional layer of cache. + /// and State after not finding data inside StateCache will try to find it inside BundleState. + /// + /// On update Bundle state will be changed and updated. + pub fn with_bundle_prestate(self, bundle: BundleState) -> Self { + Self { + with_bundle_prestate: Some(bundle), + ..self + } + } + + /// Make transitions and update bundle state. + /// + /// This is needed option if we want to create reverts + /// and getting output of changed states. + pub fn with_bundle_update(self) -> Self { + Self { + with_bundle_update: true, + ..self + } + } + + /// It will use different cache for the state. If set, it will ignore bundle prestate. + /// and will ignore `without_state_clear` flag as cache contains its own state_clear flag. + /// + /// This is useful for testing. + pub fn with_cached_prestate(self, cache: CacheState) -> Self { + Self { + with_cache_prestate: Some(cache), + ..self + } + } + + /// Starts the thread that will take transitions and do merge to the bundle state + /// in the background. + pub fn with_background_transition_merge(self) -> Self { + Self { + with_background_transition_merge: true, + ..self + } + } + + pub fn with_block_hashes(self, block_hashes: BTreeMap) -> Self { + Self { + with_block_hashes: block_hashes, + ..self + } + } + + pub fn build(mut self) -> State { + let use_preloaded_bundle = if self.with_cache_prestate.is_some() { + self.with_bundle_prestate = None; + false + } else { + self.with_bundle_prestate.is_some() + }; + State { + cache: self + .with_cache_prestate + .unwrap_or_else(|| CacheState::new(self.with_state_clear)), + database: self.database, + transition_state: self.with_bundle_update.then(TransitionState::default), + bundle_state: self.with_bundle_prestate.unwrap_or_default(), + use_preloaded_bundle, + block_hashes: self.with_block_hashes, + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/transition_account.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/transition_account.md new file mode 100644 index 00000000..71630d03 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/transition_account.md @@ -0,0 +1,152 @@ +# ๐Ÿฆ€ transition_account.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/transition_account.rs) + +```rust +use super::{AccountRevert, BundleAccount, StorageWithOriginalValues}; +use crate::db::AccountStatus; +use revm_interpreter::primitives::{hash_map, AccountInfo, Bytecode, B256, I256, U256}; + +/// Account Created when EVM state is merged to cache state. +/// And it is sent to Block state. +/// +/// It is used when block state gets merged to bundle state to +/// create needed Reverts. +#[derive(Clone, Debug, PartialEq, Eq, Default)] +pub struct TransitionAccount { + pub info: Option, + pub status: AccountStatus, + /// Previous account info is needed for account that got initially loaded. + /// Initially loaded account are not present inside bundle and are needed + /// to generate Reverts. + pub previous_info: Option, + /// Mostly needed when previous status Loaded/LoadedEmpty. + pub previous_status: AccountStatus, + /// Storage contains both old and new account + pub storage: StorageWithOriginalValues, + /// If there is transition that clears the storage we should mark it here and + /// delete all storages in BundleState. This flag is needed if we have transition + /// between Destroyed states from DestroyedChanged-> DestroyedAgain-> DestroyedChanged + /// in the end transition that we would have would be `DestroyedChanged->DestroyedChanged` + /// and with only that info we couldn't decide what to do. + pub storage_was_destroyed: bool, +} + +impl TransitionAccount { + /// Create new LoadedEmpty account. + pub fn new_empty_eip161(storage: StorageWithOriginalValues) -> Self { + Self { + info: Some(AccountInfo::default()), + status: AccountStatus::InMemoryChange, + previous_info: None, + previous_status: AccountStatus::LoadedNotExisting, + storage, + storage_was_destroyed: false, + } + } + + /// Return new contract bytecode if it is changed or newly created. + pub fn has_new_contract(&self) -> Option<(B256, &Bytecode)> { + let present_new_codehash = self.info.as_ref().map(|info| &info.code_hash); + let previous_codehash = self.previous_info.as_ref().map(|info| &info.code_hash); + if present_new_codehash != previous_codehash { + return self + .info + .as_ref() + .and_then(|info| info.code.as_ref().map(|c| (info.code_hash, c))); + } + None + } + + /// Return the balance of account before transition. + pub fn previous_balance(&self) -> U256 { + self.previous_info + .as_ref() + .map(|info| info.balance) + .unwrap_or_default() + } + + /// Return the balance of account after transition. + pub fn current_balance(&self) -> U256 { + self.info + .as_ref() + .map(|info| info.balance) + .unwrap_or_default() + } + + /// Calculate the change in account's balance for this transition. + /// Returns `None` if delta does not fit in [I256]. + pub fn balance_delta(&self) -> Option { + let previous_balance = self.previous_balance(); + let current_balance = self.current_balance(); + let delta = I256::try_from(previous_balance.abs_diff(current_balance)).ok()?; + if current_balance >= previous_balance { + Some(delta) + } else { + delta.checked_neg() + } + } + + /// Update new values of transition. Don't override old values. + /// Both account info and old storages need to be left intact. + pub fn update(&mut self, other: Self) { + self.info = other.info.clone(); + self.status = other.status; + + // if transition is from some to destroyed drop the storage. + // This need to be done here as it is one increment of the state. + if matches!( + other.status, + AccountStatus::Destroyed | AccountStatus::DestroyedAgain + ) { + self.storage = other.storage; + self.storage_was_destroyed = true; + } else { + // update changed values to this transition. + for (key, slot) in other.storage.into_iter() { + match self.storage.entry(key) { + hash_map::Entry::Vacant(entry) => { + entry.insert(slot); + } + hash_map::Entry::Occupied(mut entry) => { + let value = entry.get_mut(); + // if new value is same as original value. Remove storage entry. + if value.original_value() == slot.present_value() { + entry.remove(); + } else { + // if value is different, update transition present value; + value.present_value = slot.present_value; + } + } + } + } + } + } + + /// Consume Self and create account revert from it. + pub fn create_revert(self) -> Option { + let mut previous_account = self.original_bundle_account(); + previous_account.update_and_create_revert(self) + } + + /// Present bundle account + pub fn present_bundle_account(&self) -> BundleAccount { + BundleAccount { + info: self.info.clone(), + original_info: self.previous_info.clone(), + storage: self.storage.clone(), + status: self.status, + } + } + + /// Original bundle account + fn original_bundle_account(&self) -> BundleAccount { + BundleAccount { + info: self.previous_info.clone(), + original_info: self.previous_info.clone(), + storage: StorageWithOriginalValues::new(), + status: self.previous_status, + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/transition_state.md b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/transition_state.md new file mode 100644 index 00000000..5f57a9a3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/db/states/transition_state.md @@ -0,0 +1,43 @@ +# ๐Ÿฆ€ transition_state.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/db/states/transition_state.rs) + +```rust +use super::TransitionAccount; +use revm_interpreter::primitives::{hash_map::Entry, Address, HashMap}; +use std::vec::Vec; + +#[derive(Clone, Default, Debug, PartialEq, Eq)] +pub struct TransitionState { + /// Block state account with account state + pub transitions: HashMap, +} + +impl TransitionState { + /// Create new transition state with one transition. + pub fn single(address: Address, transition: TransitionAccount) -> Self { + let mut transitions = HashMap::new(); + transitions.insert(address, transition); + TransitionState { transitions } + } + + /// Return transition id and all account transitions. Leave empty transition map. + pub fn take(&mut self) -> TransitionState { + core::mem::take(self) + } + + pub fn add_transitions(&mut self, transitions: Vec<(Address, TransitionAccount)>) { + for (address, account) in transitions { + match self.transitions.entry(address) { + Entry::Occupied(entry) => { + let entry = entry.into_mut(); + entry.update(account); + } + Entry::Vacant(entry) => { + entry.insert(account); + } + } + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/evm.md b/docs/revm-python-spec/revm-verif/revm/revm/src/evm.md new file mode 100644 index 00000000..0d63321d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/evm.md @@ -0,0 +1,505 @@ +# ๐Ÿฆ€ evm.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/evm.rs) + +```rust +use crate::{ + builder::{EvmBuilder, HandlerStage, SetGenericStage}, + db::{Database, DatabaseCommit, EmptyDB}, + handler::Handler, + interpreter::{ + opcode::InstructionTables, Host, Interpreter, InterpreterAction, LoadAccountResult, + SStoreResult, SelfDestructResult, SharedMemory, + }, + primitives::{ + specification::SpecId, Address, BlockEnv, Bytecode, CfgEnv, EVMError, EVMResult, Env, + EnvWithHandlerCfg, ExecutionResult, HandlerCfg, Log, ResultAndState, TransactTo, TxEnv, + B256, U256, + }, + Context, ContextWithHandlerCfg, Frame, FrameOrResult, FrameResult, +}; +use core::fmt; +use revm_interpreter::{CallInputs, CreateInputs}; +use std::vec::Vec; + +/// EVM call stack limit. +pub const CALL_STACK_LIMIT: u64 = 1024; + +/// EVM instance containing both internal EVM context and external context +/// and the handler that dictates the logic of EVM (or hardfork specification). +pub struct Evm<'a, EXT, DB: Database> { + /// Context of execution, containing both EVM and external context. + pub context: Context, + /// Handler is a component of the of EVM that contains all the logic. Handler contains specification id + /// and it different depending on the specified fork. + pub handler: Handler<'a, Self, EXT, DB>, +} + +impl fmt::Debug for Evm<'_, EXT, DB> +where + EXT: fmt::Debug, + DB: Database + fmt::Debug, + DB::Error: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Evm") + .field("evm context", &self.context.evm) + .finish_non_exhaustive() + } +} + +impl Evm<'_, EXT, DB> { + /// Commit the changes to the database. + pub fn transact_commit(&mut self) -> Result> { + let ResultAndState { result, state } = self.transact()?; + self.context.evm.db.commit(state); + Ok(result) + } +} + +impl<'a> Evm<'a, (), EmptyDB> { + /// Returns evm builder with empty database and empty external context. + pub fn builder() -> EvmBuilder<'a, SetGenericStage, (), EmptyDB> { + EvmBuilder::default() + } +} + +impl<'a, EXT, DB: Database> Evm<'a, EXT, DB> { + /// Create new EVM. + pub fn new( + mut context: Context, + handler: Handler<'a, Self, EXT, DB>, + ) -> Evm<'a, EXT, DB> { + context.evm.journaled_state.set_spec_id(handler.cfg.spec_id); + Evm { context, handler } + } + + /// Allow for evm setting to be modified by feeding current evm + /// into the builder for modifications. + pub fn modify(self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + EvmBuilder::new(self) + } +} + +impl Evm<'_, EXT, DB> { + /// Returns specification (hardfork) that the EVM is instanced with. + /// + /// SpecId depends on the handler. + pub fn spec_id(&self) -> SpecId { + self.handler.cfg.spec_id + } + + /// Pre verify transaction by checking Environment, initial gas spend and if caller + /// has enough balance to pay for the gas. + #[inline] + pub fn preverify_transaction(&mut self) -> Result<(), EVMError> { + let output = self.preverify_transaction_inner().map(|_| ()); + self.clear(); + output + } + + /// Calls clear handle of post execution to clear the state for next execution. + fn clear(&mut self) { + self.handler.post_execution().clear(&mut self.context); + } + + /// Transact pre-verified transaction + /// + /// This function will not validate the transaction. + #[inline] + pub fn transact_preverified(&mut self) -> EVMResult { + let initial_gas_spend = self + .handler + .validation() + .initial_tx_gas(&self.context.evm.env) + .map_err(|e| { + self.clear(); + e + })?; + let output = self.transact_preverified_inner(initial_gas_spend); + let output = self.handler.post_execution().end(&mut self.context, output); + self.clear(); + output + } + + /// Pre verify transaction inner. + #[inline] + fn preverify_transaction_inner(&mut self) -> Result> { + self.handler.validation().env(&self.context.evm.env)?; + let initial_gas_spend = self + .handler + .validation() + .initial_tx_gas(&self.context.evm.env)?; + self.handler + .validation() + .tx_against_state(&mut self.context)?; + Ok(initial_gas_spend) + } + + /// Transact transaction + /// + /// This function will validate the transaction. + #[inline] + pub fn transact(&mut self) -> EVMResult { + let initial_gas_spend = self.preverify_transaction_inner().map_err(|e| { + self.clear(); + e + })?; + + let output = self.transact_preverified_inner(initial_gas_spend); + let output = self.handler.post_execution().end(&mut self.context, output); + self.clear(); + output + } + + /// Returns the reference of handler configuration + #[inline] + pub fn handler_cfg(&self) -> &HandlerCfg { + &self.handler.cfg + } + + /// Returns the reference of Env configuration + #[inline] + pub fn cfg(&self) -> &CfgEnv { + &self.env().cfg + } + + /// Returns the mutable reference of Env configuration + #[inline] + pub fn cfg_mut(&mut self) -> &mut CfgEnv { + &mut self.context.evm.env.cfg + } + + /// Returns the reference of transaction + #[inline] + pub fn tx(&self) -> &TxEnv { + &self.context.evm.env.tx + } + + /// Returns the mutable reference of transaction + #[inline] + pub fn tx_mut(&mut self) -> &mut TxEnv { + &mut self.context.evm.env.tx + } + + /// Returns the reference of database + #[inline] + pub fn db(&self) -> &DB { + &self.context.evm.db + } + + /// Returns the mutable reference of database + #[inline] + pub fn db_mut(&mut self) -> &mut DB { + &mut self.context.evm.db + } + + /// Returns the reference of block + #[inline] + pub fn block(&self) -> &BlockEnv { + &self.context.evm.env.block + } + + /// Returns the mutable reference of block + #[inline] + pub fn block_mut(&mut self) -> &mut BlockEnv { + &mut self.context.evm.env.block + } + + /// Modify spec id, this will create new EVM that matches this spec id. + pub fn modify_spec_id(&mut self, spec_id: SpecId) { + self.handler.modify_spec_id(spec_id); + } + + /// Returns internal database and external struct. + #[inline] + pub fn into_context(self) -> Context { + self.context + } + + /// Returns database and [`EnvWithHandlerCfg`]. + #[inline] + pub fn into_db_and_env_with_handler_cfg(self) -> (DB, EnvWithHandlerCfg) { + ( + self.context.evm.inner.db, + EnvWithHandlerCfg { + env: self.context.evm.inner.env, + handler_cfg: self.handler.cfg, + }, + ) + } + + /// Returns [Context] and [HandlerCfg]. + #[inline] + pub fn into_context_with_handler_cfg(self) -> ContextWithHandlerCfg { + ContextWithHandlerCfg::new(self.context, self.handler.cfg) + } + + /// Starts the main loop and returns outcome of the execution. + pub fn start_the_loop( + &mut self, + first_frame: Frame, + ) -> Result> { + // take instruction table + let table = self + .handler + .take_instruction_table() + .expect("Instruction table should be present"); + + // run main loop + let frame_result = match &table { + InstructionTables::Plain(table) => self.run_the_loop(table, first_frame), + InstructionTables::Boxed(table) => self.run_the_loop(table, first_frame), + }; + + // return back instruction table + self.handler.set_instruction_table(table); + + frame_result + } + + /// Runs main call loop. + #[inline] + pub fn run_the_loop( + &mut self, + instruction_table: &[FN; 256], + first_frame: Frame, + ) -> Result> + where + FN: Fn(&mut Interpreter, &mut Self), + { + let mut call_stack: Vec = Vec::with_capacity(1025); + call_stack.push(first_frame); + + #[cfg(feature = "memory_limit")] + let mut shared_memory = + SharedMemory::new_with_memory_limit(self.context.evm.env.cfg.memory_limit); + #[cfg(not(feature = "memory_limit"))] + let mut shared_memory = SharedMemory::new(); + + shared_memory.new_context(); + + // peek last stack frame. + let mut stack_frame = call_stack.last_mut().unwrap(); + + loop { + // run interpreter + let interpreter = &mut stack_frame.frame_data_mut().interpreter; + let next_action = interpreter.run(shared_memory, instruction_table, self); + + // take error and break the loop if there is any. + // This error is set From Interpreter when it's interacting with Host. + self.context.evm.take_error()?; + // take shared memory back. + shared_memory = interpreter.take_memory(); + + let exec = &mut self.handler.execution; + let frame_or_result = match next_action { + InterpreterAction::Call { inputs } => exec.call(&mut self.context, inputs)?, + InterpreterAction::Create { inputs } => exec.create(&mut self.context, inputs)?, + InterpreterAction::EOFCreate { inputs } => { + exec.eofcreate(&mut self.context, inputs)? + } + InterpreterAction::Return { result } => { + // free memory context. + shared_memory.free_context(); + + // pop last frame from the stack and consume it to create FrameResult. + let returned_frame = call_stack + .pop() + .expect("We just returned from Interpreter frame"); + + let ctx = &mut self.context; + FrameOrResult::Result(match returned_frame { + Frame::Call(frame) => { + // return_call + FrameResult::Call(exec.call_return(ctx, frame, result)?) + } + Frame::Create(frame) => { + // return_create + FrameResult::Create(exec.create_return(ctx, frame, result)?) + } + Frame::EOFCreate(frame) => { + // return_eofcreate + FrameResult::EOFCreate(exec.eofcreate_return(ctx, frame, result)?) + } + }) + } + InterpreterAction::None => unreachable!("InterpreterAction::None is not expected"), + }; + + // handle result + match frame_or_result { + FrameOrResult::Frame(frame) => { + shared_memory.new_context(); + call_stack.push(frame); + stack_frame = call_stack.last_mut().unwrap(); + } + FrameOrResult::Result(result) => { + let Some(top_frame) = call_stack.last_mut() else { + // Break the look if there are no more frames. + return Ok(result); + }; + stack_frame = top_frame; + let ctx = &mut self.context; + // Insert result to the top frame. + match result { + FrameResult::Call(outcome) => { + // return_call + exec.insert_call_outcome(ctx, stack_frame, &mut shared_memory, outcome)? + } + FrameResult::Create(outcome) => { + // return_create + exec.insert_create_outcome(ctx, stack_frame, outcome)? + } + FrameResult::EOFCreate(outcome) => { + // return_eofcreate + exec.insert_eofcreate_outcome(ctx, stack_frame, outcome)? + } + } + } + } + } + } + + /// Transact pre-verified transaction. + fn transact_preverified_inner(&mut self, initial_gas_spend: u64) -> EVMResult { + let ctx = &mut self.context; + let pre_exec = self.handler.pre_execution(); + + // load access list and beneficiary if needed. + pre_exec.load_accounts(ctx)?; + + // load precompiles + let precompiles = pre_exec.load_precompiles(); + ctx.evm.set_precompiles(precompiles); + + // deduce caller balance with its limit. + pre_exec.deduct_caller(ctx)?; + + let gas_limit = ctx.evm.env.tx.gas_limit - initial_gas_spend; + + let exec = self.handler.execution(); + // call inner handling of call/create + let first_frame_or_result = match ctx.evm.env.tx.transact_to { + TransactTo::Call(_) => exec.call( + ctx, + CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + )?, + TransactTo::Create => exec.create( + ctx, + CreateInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + )?, + }; + + // Starts the main running loop. + let mut result = match first_frame_or_result { + FrameOrResult::Frame(first_frame) => self.start_the_loop(first_frame)?, + FrameOrResult::Result(result) => result, + }; + + let ctx = &mut self.context; + + // handle output of call/create calls. + self.handler + .execution() + .last_frame_return(ctx, &mut result)?; + + let post_exec = self.handler.post_execution(); + // Reimburse the caller + post_exec.reimburse_caller(ctx, result.gas())?; + // Reward beneficiary + post_exec.reward_beneficiary(ctx, result.gas())?; + // Returns output of transaction. + post_exec.output(ctx, result) + } +} + +impl Host for Evm<'_, EXT, DB> { + fn env(&self) -> &Env { + &self.context.evm.env + } + + fn env_mut(&mut self) -> &mut Env { + &mut self.context.evm.env + } + + fn block_hash(&mut self, number: U256) -> Option { + self.context + .evm + .block_hash(number) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + + fn load_account(&mut self, address: Address) -> Option { + self.context + .evm + .load_account_exist(address) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + + fn balance(&mut self, address: Address) -> Option<(U256, bool)> { + self.context + .evm + .balance(address) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + + fn code(&mut self, address: Address) -> Option<(Bytecode, bool)> { + self.context + .evm + .code(address) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + + fn code_hash(&mut self, address: Address) -> Option<(B256, bool)> { + self.context + .evm + .code_hash(address) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + + fn sload(&mut self, address: Address, index: U256) -> Option<(U256, bool)> { + self.context + .evm + .sload(address, index) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + + fn sstore(&mut self, address: Address, index: U256, value: U256) -> Option { + self.context + .evm + .sstore(address, index, value) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } + + fn tload(&mut self, address: Address, index: U256) -> U256 { + self.context.evm.tload(address, index) + } + + fn tstore(&mut self, address: Address, index: U256, value: U256) { + self.context.evm.tstore(address, index, value) + } + + fn log(&mut self, log: Log) { + self.context.evm.journaled_state.log(log); + } + + fn selfdestruct(&mut self, address: Address, target: Address) -> Option { + self.context + .evm + .inner + .journaled_state + .selfdestruct(address, target, &mut self.context.evm.inner.db) + .map_err(|e| self.context.evm.error = Err(e)) + .ok() + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/frame.md b/docs/revm-python-spec/revm-verif/revm/revm/src/frame.md new file mode 100644 index 00000000..88b93ee9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/frame.md @@ -0,0 +1,308 @@ +# ๐Ÿฆ€ frame.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/frame.rs) + +```rust +use crate::{ + interpreter::Interpreter, + primitives::{Address, Output}, + JournalCheckpoint, +}; +use core::ops::Range; +use revm_interpreter::{ + CallOutcome, CreateOutcome, EOFCreateOutcome, Gas, InstructionResult, InterpreterResult, +}; +use std::boxed::Box; + +/// Call CallStackFrame. +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CallFrame { + /// Call frame has return memory range where output will be stored. + pub return_memory_range: Range, + /// Frame data. + pub frame_data: FrameData, +} + +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateFrame { + /// Create frame has a created address. + pub created_address: Address, + /// Frame data. + pub frame_data: FrameData, +} + +/// Eof Create Frame. +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct EOFCreateFrame { + pub created_address: Address, + pub return_memory_range: Range, + pub frame_data: FrameData, +} + +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct FrameData { + /// Journal checkpoint. + pub checkpoint: JournalCheckpoint, + /// Interpreter. + pub interpreter: Interpreter, +} + +/// Call stack frame. +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum Frame { + Call(Box), + Create(Box), + EOFCreate(Box), +} + +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum FrameResult { + Call(CallOutcome), + Create(CreateOutcome), + EOFCreate(EOFCreateOutcome), +} + +impl FrameResult { + /// Casts frame result to interpreter result. + #[inline] + pub fn into_interpreter_result(self) -> InterpreterResult { + match self { + FrameResult::Call(outcome) => outcome.result, + FrameResult::Create(outcome) => outcome.result, + FrameResult::EOFCreate(outcome) => outcome.result, + } + } + + /// Returns execution output. + #[inline] + pub fn output(&self) -> Output { + match self { + FrameResult::Call(outcome) => Output::Call(outcome.result.output.clone()), + FrameResult::Create(outcome) => { + Output::Create(outcome.result.output.clone(), outcome.address) + } + FrameResult::EOFCreate(_) => { + panic!("EOFCreate can't be called from external world."); + } + } + } + + /// Returns reference to gas. + #[inline] + pub fn gas(&self) -> &Gas { + match self { + FrameResult::Call(outcome) => &outcome.result.gas, + FrameResult::Create(outcome) => &outcome.result.gas, + FrameResult::EOFCreate(outcome) => &outcome.result.gas, + } + } + + /// Returns mutable reference to interpreter result. + #[inline] + pub fn gas_mut(&mut self) -> &mut Gas { + match self { + FrameResult::Call(outcome) => &mut outcome.result.gas, + FrameResult::Create(outcome) => &mut outcome.result.gas, + FrameResult::EOFCreate(outcome) => &mut outcome.result.gas, + } + } + + /// Returns reference to interpreter result. + #[inline] + pub fn interpreter_result(&self) -> &InterpreterResult { + match self { + FrameResult::Call(outcome) => &outcome.result, + FrameResult::Create(outcome) => &outcome.result, + FrameResult::EOFCreate(outcome) => &outcome.result, + } + } + + /// Returns mutable reference to interpreter result. + #[inline] + pub fn interpreter_result_mut(&mut self) -> &InterpreterResult { + match self { + FrameResult::Call(outcome) => &mut outcome.result, + FrameResult::Create(outcome) => &mut outcome.result, + FrameResult::EOFCreate(outcome) => &mut outcome.result, + } + } + + /// Return Instruction result. + #[inline] + pub fn instruction_result(&self) -> InstructionResult { + self.interpreter_result().result + } +} + +/// Contains either a frame or a result. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum FrameOrResult { + /// Boxed call or create frame. + Frame(Frame), + /// Call or create result. + Result(FrameResult), +} + +impl Frame { + pub fn new_create( + created_address: Address, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Frame::Create(Box::new(CreateFrame { + created_address, + frame_data: FrameData { + checkpoint, + interpreter, + }, + })) + } + + pub fn new_call( + return_memory_range: Range, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Frame::Call(Box::new(CallFrame { + return_memory_range, + frame_data: FrameData { + checkpoint, + interpreter, + }, + })) + } + + /// Returns true if frame is call frame. + pub fn is_call(&self) -> bool { + matches!(self, Frame::Call { .. }) + } + + /// Returns true if frame is create frame. + pub fn is_create(&self) -> bool { + matches!(self, Frame::Create { .. }) + } + + /// Returns created address if frame is create otherwise returns None. + pub fn created_address(&self) -> Option
{ + match self { + Frame::Create(create_frame) => Some(create_frame.created_address), + _ => None, + } + } + + /// Takes frame and returns frame data. + pub fn into_frame_data(self) -> FrameData { + match self { + Frame::Call(call_frame) => call_frame.frame_data, + Frame::Create(create_frame) => create_frame.frame_data, + Frame::EOFCreate(eof_create_frame) => eof_create_frame.frame_data, + } + } + + /// Returns reference to frame data. + pub fn frame_data(&self) -> &FrameData { + match self { + Self::Call(call_frame) => &call_frame.frame_data, + Self::Create(create_frame) => &create_frame.frame_data, + Self::EOFCreate(eof_create_frame) => &eof_create_frame.frame_data, + } + } + + /// Returns mutable reference to frame data. + pub fn frame_data_mut(&mut self) -> &mut FrameData { + match self { + Self::Call(call_frame) => &mut call_frame.frame_data, + Self::Create(create_frame) => &mut create_frame.frame_data, + Self::EOFCreate(eof_create_frame) => &mut eof_create_frame.frame_data, + } + } + + /// Returns a reference to the interpreter. + pub fn interpreter(&self) -> &Interpreter { + &self.frame_data().interpreter + } + + /// Returns a mutable reference to the interpreter. + pub fn interpreter_mut(&mut self) -> &mut Interpreter { + &mut self.frame_data_mut().interpreter + } +} + +impl FrameOrResult { + /// Creates new create frame. + pub fn new_create_frame( + created_address: Address, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Self::Frame(Frame::new_create(created_address, checkpoint, interpreter)) + } + + pub fn new_eofcreate_frame( + created_address: Address, + return_memory_range: Range, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Self::Frame(Frame::EOFCreate(Box::new(EOFCreateFrame { + created_address, + return_memory_range, + frame_data: FrameData { + checkpoint, + interpreter, + }, + }))) + } + + /// Creates new call frame. + pub fn new_call_frame( + return_memory_range: Range, + checkpoint: JournalCheckpoint, + interpreter: Interpreter, + ) -> Self { + Self::Frame(Frame::new_call( + return_memory_range, + checkpoint, + interpreter, + )) + } + + /// Creates new create result. + pub fn new_create_result( + interpreter_result: InterpreterResult, + address: Option
, + ) -> Self { + FrameOrResult::Result(FrameResult::Create(CreateOutcome { + result: interpreter_result, + address, + })) + } + + pub fn new_eofcreate_result( + interpreter_result: InterpreterResult, + address: Address, + return_memory_range: Range, + ) -> Self { + FrameOrResult::Result(FrameResult::EOFCreate(EOFCreateOutcome { + result: interpreter_result, + address, + return_memory_range, + })) + } + + pub fn new_call_result( + interpreter_result: InterpreterResult, + memory_offset: Range, + ) -> Self { + FrameOrResult::Result(FrameResult::Call(CallOutcome { + result: interpreter_result, + memory_offset, + })) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler.md new file mode 100644 index 00000000..69e5150d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler.md @@ -0,0 +1,237 @@ +# ๐Ÿฆ€ handler.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler.rs) + +```rust +// Modules. +mod handle_types; +pub mod mainnet; +pub mod register; + +// Exports. +pub use handle_types::*; + +// Includes. +use crate::{ + interpreter::{opcode::InstructionTables, Host}, + primitives::{db::Database, spec_to_generic, HandlerCfg, Spec, SpecId}, + Evm, +}; +use register::{EvmHandler, HandleRegisters}; +use std::vec::Vec; + +use self::register::{HandleRegister, HandleRegisterBox}; + +/// Handler acts as a proxy and allow to define different behavior for different +/// sections of the code. This allows nice integration of different chains or +/// to disable some mainnet behavior. +pub struct Handler<'a, H: Host + 'a, EXT, DB: Database> { + /// Handler configuration. + pub cfg: HandlerCfg, + /// Instruction table type. + pub instruction_table: Option>, + /// Registers that will be called on initialization. + pub registers: Vec>, + /// Validity handles. + pub validation: ValidationHandler<'a, EXT, DB>, + /// Pre execution handle. + pub pre_execution: PreExecutionHandler<'a, EXT, DB>, + /// Post Execution handle. + pub post_execution: PostExecutionHandler<'a, EXT, DB>, + /// Execution loop that handles frames. + pub execution: ExecutionHandler<'a, EXT, DB>, +} + +impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> { + /// Created new Handler with given configuration. + /// + /// Internally it calls `mainnet_with_spec` with the given spec id. + /// Or `optimism_with_spec` if the optimism feature is enabled and `cfg.is_optimism` is set. + pub fn new(cfg: HandlerCfg) -> Self { + cfg_if::cfg_if! { + if #[cfg(feature = "optimism")] { + if cfg.is_optimism { + Handler::optimism_with_spec(cfg.spec_id) + } else { + Handler::mainnet_with_spec(cfg.spec_id) + } + } else { + Handler::mainnet_with_spec(cfg.spec_id) + } + } + } + + /// Default handler for Ethereum mainnet. + pub fn mainnet() -> Self { + Self { + cfg: HandlerCfg::new(SPEC::SPEC_ID), + instruction_table: Some(InstructionTables::new_plain::()), + registers: Vec::new(), + validation: ValidationHandler::new::(), + pre_execution: PreExecutionHandler::new::(), + post_execution: PostExecutionHandler::new::(), + execution: ExecutionHandler::new::(), + } + } + + /// Returns `true` if the optimism feature is enabled and flag is set to `true`. + pub fn is_optimism(&self) -> bool { + self.cfg.is_optimism() + } + + /// Handler for optimism + #[cfg(feature = "optimism")] + pub fn optimism() -> Self { + let mut handler = Self::mainnet::(); + handler.cfg.is_optimism = true; + handler.append_handler_register(HandleRegisters::Plain( + crate::optimism::optimism_handle_register::, + )); + handler + } + + /// Optimism with spec. Similar to [`Self::mainnet_with_spec`]. + #[cfg(feature = "optimism")] + pub fn optimism_with_spec(spec_id: SpecId) -> Self { + spec_to_generic!(spec_id, Self::optimism::()) + } + + /// Creates handler with variable spec id, inside it will call `mainnet::` for + /// appropriate spec. + pub fn mainnet_with_spec(spec_id: SpecId) -> Self { + spec_to_generic!(spec_id, Self::mainnet::()) + } + + /// Specification ID. + pub fn cfg(&self) -> HandlerCfg { + self.cfg + } + + /// Take instruction table. + pub fn take_instruction_table(&mut self) -> Option>> { + self.instruction_table.take() + } + + /// Set instruction table. + pub fn set_instruction_table(&mut self, table: InstructionTables<'a, Evm<'a, EXT, DB>>) { + self.instruction_table = Some(table); + } + + /// Returns reference to pre execution handler. + pub fn pre_execution(&self) -> &PreExecutionHandler<'a, EXT, DB> { + &self.pre_execution + } + + /// Returns reference to pre execution handler. + pub fn post_execution(&self) -> &PostExecutionHandler<'a, EXT, DB> { + &self.post_execution + } + + /// Returns reference to frame handler. + pub fn execution(&self) -> &ExecutionHandler<'a, EXT, DB> { + &self.execution + } + + /// Returns reference to validation handler. + pub fn validation(&self) -> &ValidationHandler<'a, EXT, DB> { + &self.validation + } + + /// Append handle register. + pub fn append_handler_register(&mut self, register: HandleRegisters) { + register.register(self); + self.registers.push(register); + } + + /// Append plain handle register. + pub fn append_handler_register_plain(&mut self, register: HandleRegister) { + register(self); + self.registers.push(HandleRegisters::Plain(register)); + } + + /// Append boxed handle register. + pub fn append_handler_register_box(&mut self, register: HandleRegisterBox) { + register(self); + self.registers.push(HandleRegisters::Box(register)); + } + + /// Pop last handle register and reapply all registers that are left. + pub fn pop_handle_register(&mut self) -> Option> { + let out = self.registers.pop(); + if out.is_some() { + let registers = core::mem::take(&mut self.registers); + let mut base_handler = Handler::mainnet_with_spec(self.cfg.spec_id); + // apply all registers to default handeler and raw mainnet instruction table. + for register in registers { + base_handler.append_handler_register(register) + } + *self = base_handler; + } + out + } + + /// Creates the Handler with Generic Spec. + pub fn create_handle_generic(&mut self) -> EvmHandler<'a, EXT, DB> { + let registers = core::mem::take(&mut self.registers); + let mut base_handler = Handler::mainnet::(); + // apply all registers to default handeler and raw mainnet instruction table. + for register in registers { + base_handler.append_handler_register(register) + } + base_handler + } + + /// Creates the Handler with variable SpecId, inside it will call function with Generic Spec. + pub fn modify_spec_id(&mut self, spec_id: SpecId) { + if self.cfg.spec_id == spec_id { + return; + } + + let registers = core::mem::take(&mut self.registers); + // register for optimism is added as a register, so we need to create mainnet handler here. + let mut handler = Handler::mainnet_with_spec(spec_id); + // apply all registers to default handler and raw mainnet instruction table. + for register in registers { + handler.append_handler_register(register) + } + handler.cfg = self.cfg(); + handler.cfg.spec_id = spec_id; + *self = handler; + } +} + +#[cfg(test)] +mod test { + use core::cell::RefCell; + + use crate::{db::EmptyDB, primitives::EVMError}; + use std::{rc::Rc, sync::Arc}; + + use super::*; + + #[test] + fn test_handler_register_pop() { + let register = |inner: &Rc>| -> HandleRegisterBox<(), EmptyDB> { + let inner = inner.clone(); + Box::new(move |h| { + *inner.borrow_mut() += 1; + h.post_execution.output = Arc::new(|_, _| Err(EVMError::Custom("test".to_string()))) + }) + }; + + let mut handler = EvmHandler::<(), EmptyDB>::new(HandlerCfg::new(SpecId::LATEST)); + let test = Rc::new(RefCell::new(0)); + + handler.append_handler_register_box(register(&test)); + assert_eq!(*test.borrow(), 1); + + handler.append_handler_register_box(register(&test)); + assert_eq!(*test.borrow(), 2); + + assert!(handler.pop_handle_register().is_some()); + + // first handler is reapplied + assert_eq!(*test.borrow(), 3); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types.md new file mode 100644 index 00000000..4fff2278 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types.md @@ -0,0 +1,31 @@ +# ๐Ÿฆ€ handle_types.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/handle_types.rs) + +```rust +// Modules + +pub mod execution; +pub mod post_execution; +pub mod pre_execution; +pub mod validation; + +// Exports + +pub use validation::{ + ValidateEnvHandle, ValidateInitialTxGasHandle, ValidateTxEnvAgainstState, ValidationHandler, +}; + +pub use execution::{ + ExecutionHandler, FrameCallHandle, FrameCallReturnHandle, FrameCreateHandle, + FrameCreateReturnHandle, InsertCallOutcomeHandle, InsertCreateOutcomeHandle, +}; + +pub use pre_execution::{ + DeductCallerHandle, LoadAccountsHandle, LoadPrecompilesHandle, PreExecutionHandler, +}; + +pub use post_execution::{ + EndHandle, OutputHandle, PostExecutionHandler, ReimburseCallerHandle, RewardBeneficiaryHandle, +}; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/execution.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/execution.md new file mode 100644 index 00000000..226e124b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/execution.md @@ -0,0 +1,264 @@ +# ๐Ÿฆ€ execution.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/handle_types/execution.rs) + +```rust +use crate::{ + frame::EOFCreateFrame, + handler::mainnet, + interpreter::{CallInputs, CreateInputs, SharedMemory}, + primitives::{db::Database, EVMError, Spec}, + CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, +}; +use std::{boxed::Box, sync::Arc}; + +use revm_interpreter::{ + CallOutcome, CreateOutcome, EOFCreateInput, EOFCreateOutcome, InterpreterResult, +}; + +/// Handles first frame return handle. +pub type LastFrameReturnHandle<'a, EXT, DB> = Arc< + dyn Fn(&mut Context, &mut FrameResult) -> Result<(), EVMError<::Error>> + + 'a, +>; + +/// Handle sub call. +pub type FrameCallHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + Box, + ) -> Result::Error>> + + 'a, +>; + +/// Handle call return +pub type FrameCallReturnHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + Box, + InterpreterResult, + ) -> Result::Error>> + + 'a, +>; + +/// Insert call outcome to the parent +pub type InsertCallOutcomeHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + &mut Frame, + &mut SharedMemory, + CallOutcome, + ) -> Result<(), EVMError<::Error>> + + 'a, +>; + +/// Handle sub create. +pub type FrameCreateHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + Box, + ) -> Result::Error>> + + 'a, +>; + +/// Handle create return +pub type FrameCreateReturnHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + Box, + InterpreterResult, + ) -> Result::Error>> + + 'a, +>; + +/// Insert call outcome to the parent +pub type InsertCreateOutcomeHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + &mut Frame, + CreateOutcome, + ) -> Result<(), EVMError<::Error>> + + 'a, +>; + +/// Handle EOF sub create. +pub type FrameEOFCreateHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + Box, + ) -> Result::Error>> + + 'a, +>; + +/// Handle EOF create return +pub type FrameEOFCreateReturnHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + Box, + InterpreterResult, + ) -> Result::Error>> + + 'a, +>; + +/// Insert EOF crate outcome to the parent +pub type InsertEOFCreateOutcomeHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + &mut Frame, + EOFCreateOutcome, + ) -> Result<(), EVMError<::Error>> + + 'a, +>; + +/// Handles related to stack frames. +pub struct ExecutionHandler<'a, EXT, DB: Database> { + /// Handles last frame return, modified gas for refund and + /// sets tx gas limit. + pub last_frame_return: LastFrameReturnHandle<'a, EXT, DB>, + /// Frame call + pub call: FrameCallHandle<'a, EXT, DB>, + /// Call return + pub call_return: FrameCallReturnHandle<'a, EXT, DB>, + /// Insert call outcome + pub insert_call_outcome: InsertCallOutcomeHandle<'a, EXT, DB>, + /// Frame crate + pub create: FrameCreateHandle<'a, EXT, DB>, + /// Crate return + pub create_return: FrameCreateReturnHandle<'a, EXT, DB>, + /// Insert create outcome. + pub insert_create_outcome: InsertCreateOutcomeHandle<'a, EXT, DB>, + /// Frame EOFCreate + pub eofcreate: FrameEOFCreateHandle<'a, EXT, DB>, + /// EOFCreate return + pub eofcreate_return: FrameEOFCreateReturnHandle<'a, EXT, DB>, + /// Insert EOFCreate outcome. + pub insert_eofcreate_outcome: InsertEOFCreateOutcomeHandle<'a, EXT, DB>, +} + +impl<'a, EXT: 'a, DB: Database + 'a> ExecutionHandler<'a, EXT, DB> { + /// Creates mainnet ExecutionHandler. + pub fn new() -> Self { + Self { + last_frame_return: Arc::new(mainnet::last_frame_return::), + call: Arc::new(mainnet::call::), + call_return: Arc::new(mainnet::call_return::), + insert_call_outcome: Arc::new(mainnet::insert_call_outcome), + create: Arc::new(mainnet::create::), + create_return: Arc::new(mainnet::create_return::), + insert_create_outcome: Arc::new(mainnet::insert_create_outcome), + eofcreate: Arc::new(mainnet::eofcreate::), + eofcreate_return: Arc::new(mainnet::eofcreate_return::), + insert_eofcreate_outcome: Arc::new(mainnet::insert_eofcreate_outcome), + } + } +} + +impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { + /// Handle call return, depending on instruction result gas will be reimbursed or not. + #[inline] + pub fn last_frame_return( + &self, + context: &mut Context, + frame_result: &mut FrameResult, + ) -> Result<(), EVMError> { + (self.last_frame_return)(context, frame_result) + } + + /// Call frame call handler. + #[inline] + pub fn call( + &self, + context: &mut Context, + inputs: Box, + ) -> Result> { + (self.call)(context, inputs.clone()) + } + + /// Call registered handler for call return. + #[inline] + pub fn call_return( + &self, + context: &mut Context, + frame: Box, + interpreter_result: InterpreterResult, + ) -> Result> { + (self.call_return)(context, frame, interpreter_result) + } + + /// Call registered handler for inserting call outcome. + #[inline] + pub fn insert_call_outcome( + &self, + context: &mut Context, + frame: &mut Frame, + shared_memory: &mut SharedMemory, + outcome: CallOutcome, + ) -> Result<(), EVMError> { + (self.insert_call_outcome)(context, frame, shared_memory, outcome) + } + + /// Call Create frame + #[inline] + pub fn create( + &self, + context: &mut Context, + inputs: Box, + ) -> Result> { + (self.create)(context, inputs) + } + + /// Call handler for create return. + #[inline] + pub fn create_return( + &self, + context: &mut Context, + frame: Box, + interpreter_result: InterpreterResult, + ) -> Result> { + (self.create_return)(context, frame, interpreter_result) + } + + /// Call handler for inserting create outcome. + #[inline] + pub fn insert_create_outcome( + &self, + context: &mut Context, + frame: &mut Frame, + outcome: CreateOutcome, + ) -> Result<(), EVMError> { + (self.insert_create_outcome)(context, frame, outcome) + } + + /// Call Create frame + #[inline] + pub fn eofcreate( + &self, + context: &mut Context, + inputs: Box, + ) -> Result> { + (self.eofcreate)(context, inputs) + } + + /// Call handler for create return. + #[inline] + pub fn eofcreate_return( + &self, + context: &mut Context, + frame: Box, + interpreter_result: InterpreterResult, + ) -> Result> { + (self.eofcreate_return)(context, frame, interpreter_result) + } + + /// Call handler for inserting create outcome. + #[inline] + pub fn insert_eofcreate_outcome( + &self, + context: &mut Context, + frame: &mut Frame, + outcome: EOFCreateOutcome, + ) -> Result<(), EVMError> { + (self.insert_eofcreate_outcome)(context, frame, outcome) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/post_execution.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/post_execution.md new file mode 100644 index 00000000..21faf6b0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/post_execution.md @@ -0,0 +1,118 @@ +# ๐Ÿฆ€ post_execution.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/handle_types/post_execution.rs) + +```rust +// Includes. +use crate::{ + handler::mainnet, + interpreter::Gas, + primitives::{db::Database, EVMError, EVMResultGeneric, ResultAndState, Spec}, + Context, FrameResult, +}; +use std::sync::Arc; + +/// Reimburse the caller with ethereum it didn't spent. +pub type ReimburseCallerHandle<'a, EXT, DB> = + Arc, &Gas) -> EVMResultGeneric<(), ::Error> + 'a>; + +/// Reward beneficiary with transaction rewards. +pub type RewardBeneficiaryHandle<'a, EXT, DB> = ReimburseCallerHandle<'a, EXT, DB>; + +/// Main return handle, takes state from journal and transforms internal result to external. +pub type OutputHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + FrameResult, + ) -> Result::Error>> + + 'a, +>; + +/// End handle, takes result and state and returns final result. +/// This will be called after all the other handlers. +/// +/// It is useful for catching errors and returning them in a different way. +pub type EndHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Context, + Result::Error>>, + ) -> Result::Error>> + + 'a, +>; + +/// Clear handle, doesn't have output, its purpose is to clear the +/// context. It will be always called even on failed validation. +pub type ClearHandle<'a, EXT, DB> = Arc) + 'a>; + +/// Handles related to post execution after the stack loop is finished. +pub struct PostExecutionHandler<'a, EXT, DB: Database> { + /// Reimburse the caller with ethereum it didn't spent. + pub reimburse_caller: ReimburseCallerHandle<'a, EXT, DB>, + /// Reward the beneficiary with caller fee. + pub reward_beneficiary: RewardBeneficiaryHandle<'a, EXT, DB>, + /// Main return handle, returns the output of the transact. + pub output: OutputHandle<'a, EXT, DB>, + /// Called when execution ends. + /// End handle in comparison to output handle will be called every time after execution. + /// Output in case of error will not be called. + pub end: EndHandle<'a, EXT, DB>, + /// Clear handle will be called always. In comparison to end that + /// is called only on execution end, clear handle is called even if validation fails. + pub clear: ClearHandle<'a, EXT, DB>, +} + +impl<'a, EXT: 'a, DB: Database + 'a> PostExecutionHandler<'a, EXT, DB> { + /// Creates mainnet MainHandles. + pub fn new() -> Self { + Self { + reimburse_caller: Arc::new(mainnet::reimburse_caller::), + reward_beneficiary: Arc::new(mainnet::reward_beneficiary::), + output: Arc::new(mainnet::output::), + end: Arc::new(mainnet::end::), + clear: Arc::new(mainnet::clear::), + } + } +} + +impl<'a, EXT, DB: Database> PostExecutionHandler<'a, EXT, DB> { + /// Reimburse the caller with gas that were not spend. + pub fn reimburse_caller( + &self, + context: &mut Context, + gas: &Gas, + ) -> Result<(), EVMError> { + (self.reimburse_caller)(context, gas) + } + /// Reward beneficiary + pub fn reward_beneficiary( + &self, + context: &mut Context, + gas: &Gas, + ) -> Result<(), EVMError> { + (self.reward_beneficiary)(context, gas) + } + + /// Returns the output of transaction. + pub fn output( + &self, + context: &mut Context, + result: FrameResult, + ) -> Result> { + (self.output)(context, result) + } + + /// End handler. + pub fn end( + &self, + context: &mut Context, + end_output: Result>, + ) -> Result> { + (self.end)(context, end_output) + } + + /// Clean handler. + pub fn clear(&self, context: &mut Context) { + (self.clear)(context) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/pre_execution.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/pre_execution.md new file mode 100644 index 00000000..46d41708 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/pre_execution.md @@ -0,0 +1,64 @@ +# ๐Ÿฆ€ pre_execution.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/handle_types/pre_execution.rs) + +```rust +// Includes. +use crate::{ + handler::mainnet, + primitives::{db::Database, EVMError, EVMResultGeneric, Spec}, + Context, ContextPrecompiles, +}; +use std::sync::Arc; + +/// Loads precompiles into Evm +pub type LoadPrecompilesHandle<'a, DB> = Arc ContextPrecompiles + 'a>; + +/// Load access list accounts and beneficiary. +/// There is no need to load Caller as it is assumed that +/// it will be loaded in DeductCallerHandle. +pub type LoadAccountsHandle<'a, EXT, DB> = + Arc) -> Result<(), EVMError<::Error>> + 'a>; + +/// Deduct the caller to its limit. +pub type DeductCallerHandle<'a, EXT, DB> = + Arc) -> EVMResultGeneric<(), ::Error> + 'a>; + +/// Handles related to pre execution before the stack loop is started. +pub struct PreExecutionHandler<'a, EXT, DB: Database> { + /// Load precompiles + pub load_precompiles: LoadPrecompilesHandle<'a, DB>, + /// Main load handle + pub load_accounts: LoadAccountsHandle<'a, EXT, DB>, + /// Deduct max value from the caller. + pub deduct_caller: DeductCallerHandle<'a, EXT, DB>, +} + +impl<'a, EXT: 'a, DB: Database + 'a> PreExecutionHandler<'a, EXT, DB> { + /// Creates mainnet MainHandles. + pub fn new() -> Self { + Self { + load_precompiles: Arc::new(mainnet::load_precompiles::), + load_accounts: Arc::new(mainnet::load_accounts::), + deduct_caller: Arc::new(mainnet::deduct_caller::), + } + } +} + +impl<'a, EXT, DB: Database> PreExecutionHandler<'a, EXT, DB> { + /// Deduct caller to its limit. + pub fn deduct_caller(&self, context: &mut Context) -> Result<(), EVMError> { + (self.deduct_caller)(context) + } + + /// Main load + pub fn load_accounts(&self, context: &mut Context) -> Result<(), EVMError> { + (self.load_accounts)(context) + } + + /// Load precompiles + pub fn load_precompiles(&self) -> ContextPrecompiles { + (self.load_precompiles)() + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/validation.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/validation.md new file mode 100644 index 00000000..2dde5e99 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/handle_types/validation.md @@ -0,0 +1,66 @@ +# ๐Ÿฆ€ validation.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/handle_types/validation.rs) + +```rust +use crate::{ + handler::mainnet, + primitives::{db::Database, EVMError, Env, Spec}, + Context, +}; +use std::sync::Arc; + +/// Handle that validates env. +pub type ValidateEnvHandle<'a, DB> = + Arc Result<(), EVMError<::Error>> + 'a>; + +/// Handle that validates transaction environment against the state. +/// Second parametar is initial gas. +pub type ValidateTxEnvAgainstState<'a, EXT, DB> = + Arc) -> Result<(), EVMError<::Error>> + 'a>; + +/// Initial gas calculation handle +pub type ValidateInitialTxGasHandle<'a, DB> = + Arc Result::Error>> + 'a>; + +/// Handles related to validation. +pub struct ValidationHandler<'a, EXT, DB: Database> { + /// Validate and calculate initial transaction gas. + pub initial_tx_gas: ValidateInitialTxGasHandle<'a, DB>, + /// Validate transactions against state data. + pub tx_against_state: ValidateTxEnvAgainstState<'a, EXT, DB>, + /// Validate Env. + pub env: ValidateEnvHandle<'a, DB>, +} + +impl<'a, EXT: 'a, DB: Database + 'a> ValidationHandler<'a, EXT, DB> { + /// Create new ValidationHandles + pub fn new() -> Self { + Self { + initial_tx_gas: Arc::new(mainnet::validate_initial_tx_gas::), + env: Arc::new(mainnet::validate_env::), + tx_against_state: Arc::new(mainnet::validate_tx_against_state::), + } + } +} + +impl<'a, EXT, DB: Database> ValidationHandler<'a, EXT, DB> { + /// Validate env. + pub fn env(&self, env: &Env) -> Result<(), EVMError> { + (self.env)(env) + } + + /// Initial gas + pub fn initial_tx_gas(&self, env: &Env) -> Result> { + (self.initial_tx_gas)(env) + } + + /// Validate ttansaction against the state. + pub fn tx_against_state( + &self, + context: &mut Context, + ) -> Result<(), EVMError> { + (self.tx_against_state)(context) + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet.md new file mode 100644 index 00000000..d5868c1c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet.md @@ -0,0 +1,21 @@ +# ๐Ÿฆ€ mainnet.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/mainnet.rs) + +```rust +//! Mainnet related handlers. + +mod execution; +mod post_execution; +mod pre_execution; +mod validation; + +pub use execution::{ + call, call_return, create, create_return, eofcreate, eofcreate_return, + frame_return_with_refund_flag, insert_call_outcome, insert_create_outcome, + insert_eofcreate_outcome, last_frame_return, +}; +pub use post_execution::{clear, end, output, reimburse_caller, reward_beneficiary}; +pub use pre_execution::{deduct_caller, deduct_caller_inner, load_accounts, load_precompiles}; +pub use validation::{validate_env, validate_initial_tx_gas, validate_tx_against_state}; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/execution.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/execution.md new file mode 100644 index 00000000..e5e10e05 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/execution.md @@ -0,0 +1,241 @@ +# ๐Ÿฆ€ execution.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/mainnet/execution.rs) + +```rust +use crate::{ + db::Database, + frame::EOFCreateFrame, + interpreter::{ + return_ok, return_revert, CallInputs, CreateInputs, CreateOutcome, Gas, InstructionResult, + SharedMemory, + }, + primitives::{EVMError, Env, Spec, SpecId}, + CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, +}; +use revm_interpreter::{CallOutcome, EOFCreateInput, EOFCreateOutcome, InterpreterResult}; +use std::boxed::Box; + +/// Helper function called inside [`last_frame_return`] +#[inline] +pub fn frame_return_with_refund_flag( + env: &Env, + frame_result: &mut FrameResult, + refund_enabled: bool, +) { + let instruction_result = frame_result.interpreter_result().result; + let gas = frame_result.gas_mut(); + let remaining = gas.remaining(); + let refunded = gas.refunded(); + + // Spend the gas limit. Gas is reimbursed when the tx returns successfully. + *gas = Gas::new_spent(env.tx.gas_limit); + + match instruction_result { + return_ok!() => { + gas.erase_cost(remaining); + gas.record_refund(refunded); + } + return_revert!() => { + gas.erase_cost(remaining); + } + _ => {} + } + + // Calculate gas refund for transaction. + // If config is set to disable gas refund, it will return 0. + // If spec is set to london, it will decrease the maximum refund amount to 5th part of + // gas spend. (Before london it was 2th part of gas spend) + if refund_enabled { + // EIP-3529: Reduction in refunds + gas.set_final_refund(SPEC::SPEC_ID.is_enabled_in(SpecId::LONDON)); + } +} + +/// Handle output of the transaction +#[inline] +pub fn last_frame_return( + context: &mut Context, + frame_result: &mut FrameResult, +) -> Result<(), EVMError> { + frame_return_with_refund_flag::(&context.evm.env, frame_result, true); + Ok(()) +} + +/// Handle frame sub call. +#[inline] +pub fn call( + context: &mut Context, + inputs: Box, +) -> Result> { + context.evm.make_call_frame(&inputs) +} + +#[inline] +pub fn call_return( + context: &mut Context, + frame: Box, + interpreter_result: InterpreterResult, +) -> Result> { + context + .evm + .call_return(&interpreter_result, frame.frame_data.checkpoint); + Ok(CallOutcome::new( + interpreter_result, + frame.return_memory_range, + )) +} + +#[inline] +pub fn insert_call_outcome( + context: &mut Context, + frame: &mut Frame, + shared_memory: &mut SharedMemory, + outcome: CallOutcome, +) -> Result<(), EVMError> { + context.evm.take_error()?; + frame + .frame_data_mut() + .interpreter + .insert_call_outcome(shared_memory, outcome); + Ok(()) +} + +/// Handle frame sub create. +#[inline] +pub fn create( + context: &mut Context, + inputs: Box, +) -> Result> { + context.evm.make_create_frame(SPEC::SPEC_ID, &inputs) +} + +#[inline] +pub fn create_return( + context: &mut Context, + frame: Box, + mut interpreter_result: InterpreterResult, +) -> Result> { + context.evm.create_return::( + &mut interpreter_result, + frame.created_address, + frame.frame_data.checkpoint, + ); + Ok(CreateOutcome::new( + interpreter_result, + Some(frame.created_address), + )) +} + +#[inline] +pub fn insert_create_outcome( + context: &mut Context, + frame: &mut Frame, + outcome: CreateOutcome, +) -> Result<(), EVMError> { + context.evm.take_error()?; + frame + .frame_data_mut() + .interpreter + .insert_create_outcome(outcome); + Ok(()) +} + +/// Handle frame sub create. +#[inline] +pub fn eofcreate( + context: &mut Context, + inputs: Box, +) -> Result> { + context.evm.make_eofcreate_frame(SPEC::SPEC_ID, &inputs) +} + +#[inline] +pub fn eofcreate_return( + context: &mut Context, + frame: Box, + mut interpreter_result: InterpreterResult, +) -> Result> { + context.evm.eofcreate_return::( + &mut interpreter_result, + frame.created_address, + frame.frame_data.checkpoint, + ); + Ok(EOFCreateOutcome::new( + interpreter_result, + frame.created_address, + frame.return_memory_range, + )) +} + +#[inline] +pub fn insert_eofcreate_outcome( + context: &mut Context, + frame: &mut Frame, + outcome: EOFCreateOutcome, +) -> Result<(), EVMError> { + core::mem::replace(&mut context.evm.error, Ok(()))?; + frame + .frame_data_mut() + .interpreter + .insert_eofcreate_outcome(outcome); + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use revm_interpreter::primitives::CancunSpec; + use revm_precompile::Bytes; + + /// Creates frame result. + fn call_last_frame_return(instruction_result: InstructionResult, gas: Gas) -> Gas { + let mut env = Env::default(); + env.tx.gas_limit = 100; + + let mut first_frame = FrameResult::Call(CallOutcome::new( + InterpreterResult { + result: instruction_result, + output: Bytes::new(), + gas, + }, + 0..0, + )); + frame_return_with_refund_flag::(&env, &mut first_frame, true); + *first_frame.gas() + } + + #[test] + fn test_consume_gas() { + let gas = call_last_frame_return(InstructionResult::Stop, Gas::new(90)); + assert_eq!(gas.remaining(), 90); + assert_eq!(gas.spent(), 10); + assert_eq!(gas.refunded(), 0); + } + + // TODO + #[test] + fn test_consume_gas_with_refund() { + let mut return_gas = Gas::new(90); + return_gas.record_refund(30); + + let gas = call_last_frame_return(InstructionResult::Stop, return_gas); + assert_eq!(gas.remaining(), 90); + assert_eq!(gas.spent(), 10); + assert_eq!(gas.refunded(), 2); + + let gas = call_last_frame_return(InstructionResult::Revert, return_gas); + assert_eq!(gas.remaining(), 90); + assert_eq!(gas.spent(), 10); + assert_eq!(gas.refunded(), 0); + } + + #[test] + fn test_revert_gas() { + let gas = call_last_frame_return(InstructionResult::Revert, Gas::new(90)); + assert_eq!(gas.remaining(), 90); + assert_eq!(gas.spent(), 10); + assert_eq!(gas.refunded(), 0); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/post_execution.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/post_execution.md new file mode 100644 index 00000000..e780c8ba --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/post_execution.md @@ -0,0 +1,131 @@ +# ๐Ÿฆ€ post_execution.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/mainnet/post_execution.rs) + +```rust +use crate::{ + interpreter::{Gas, SuccessOrHalt}, + primitives::{ + db::Database, EVMError, ExecutionResult, ResultAndState, Spec, SpecId::LONDON, U256, + }, + Context, FrameResult, +}; + +/// Mainnet end handle does not change the output. +#[inline] +pub fn end( + _context: &mut Context, + evm_output: Result>, +) -> Result> { + evm_output +} + +/// Clear handle clears error and journal state. +#[inline] +pub fn clear(context: &mut Context) { + // clear error and journaled state. + let _ = context.evm.take_error(); + context.evm.inner.journaled_state.clear(); +} + +/// Reward beneficiary with gas fee. +#[inline] +pub fn reward_beneficiary( + context: &mut Context, + gas: &Gas, +) -> Result<(), EVMError> { + let beneficiary = context.evm.env.block.coinbase; + let effective_gas_price = context.evm.env.effective_gas_price(); + + // transfer fee to coinbase/beneficiary. + // EIP-1559 discard basefee for coinbase transfer. Basefee amount of gas is discarded. + let coinbase_gas_price = if SPEC::enabled(LONDON) { + effective_gas_price.saturating_sub(context.evm.env.block.basefee) + } else { + effective_gas_price + }; + + let (coinbase_account, _) = context + .evm + .inner + .journaled_state + .load_account(beneficiary, &mut context.evm.inner.db)?; + + coinbase_account.mark_touch(); + coinbase_account.info.balance = coinbase_account + .info + .balance + .saturating_add(coinbase_gas_price * U256::from(gas.spent() - gas.refunded() as u64)); + + Ok(()) +} + +#[inline] +pub fn reimburse_caller( + context: &mut Context, + gas: &Gas, +) -> Result<(), EVMError> { + let caller = context.evm.env.tx.caller; + let effective_gas_price = context.evm.env.effective_gas_price(); + + // return balance of not spend gas. + let (caller_account, _) = context + .evm + .inner + .journaled_state + .load_account(caller, &mut context.evm.inner.db)?; + + caller_account.info.balance = caller_account + .info + .balance + .saturating_add(effective_gas_price * U256::from(gas.remaining() + gas.refunded() as u64)); + + Ok(()) +} + +/// Main return handle, returns the output of the transaction. +#[inline] +pub fn output( + context: &mut Context, + result: FrameResult, +) -> Result> { + context.evm.take_error()?; + // used gas with refund calculated. + let gas_refunded = result.gas().refunded() as u64; + let final_gas_used = result.gas().spent() - gas_refunded; + let output = result.output(); + let instruction_result = result.into_interpreter_result(); + + // reset journal and return present state. + let (state, logs) = context.evm.journaled_state.finalize(); + + let result = match instruction_result.result.into() { + SuccessOrHalt::Success(reason) => ExecutionResult::Success { + reason, + gas_used: final_gas_used, + gas_refunded, + logs, + output, + }, + SuccessOrHalt::Revert => ExecutionResult::Revert { + gas_used: final_gas_used, + output: output.into_data(), + }, + SuccessOrHalt::Halt(reason) => ExecutionResult::Halt { + reason, + gas_used: final_gas_used, + }, + // Only two internal return flags. + flag @ (SuccessOrHalt::FatalExternalError + | SuccessOrHalt::InternalContinue + | SuccessOrHalt::InternalCallOrCreate) => { + panic!( + "Encountered unexpected internal return flag: {:?} with instruction result: {:?}", + flag, instruction_result + ) + } + }; + + Ok(ResultAndState { result, state }) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/pre_execution.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/pre_execution.md new file mode 100644 index 00000000..682ed011 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/pre_execution.md @@ -0,0 +1,94 @@ +# ๐Ÿฆ€ pre_execution.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/mainnet/pre_execution.rs) + +```rust +//! Handles related to the main function of the EVM. +//! +//! They handle initial setup of the EVM, call loop and the final return of the EVM + +use crate::{ + precompile::{PrecompileSpecId, Precompiles}, + primitives::{ + db::Database, + Account, EVMError, Env, Spec, + SpecId::{CANCUN, SHANGHAI}, + TransactTo, U256, + }, + Context, ContextPrecompiles, +}; + +/// Main precompile load +#[inline] +pub fn load_precompiles() -> ContextPrecompiles { + Precompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)) + .clone() + .into() +} + +/// Main load handle +#[inline] +pub fn load_accounts( + context: &mut Context, +) -> Result<(), EVMError> { + // set journaling state flag. + context.evm.journaled_state.set_spec_id(SPEC::SPEC_ID); + + // load coinbase + // EIP-3651: Warm COINBASE. Starts the `COINBASE` address warm + if SPEC::enabled(SHANGHAI) { + context.evm.inner.journaled_state.initial_account_load( + context.evm.inner.env.block.coinbase, + &[], + &mut context.evm.inner.db, + )?; + } + + context.evm.load_access_list()?; + Ok(()) +} + +/// Helper function that deducts the caller balance. +#[inline] +pub fn deduct_caller_inner(caller_account: &mut Account, env: &Env) { + // Subtract gas costs from the caller's account. + // We need to saturate the gas cost to prevent underflow in case that `disable_balance_check` is enabled. + let mut gas_cost = U256::from(env.tx.gas_limit).saturating_mul(env.effective_gas_price()); + + // EIP-4844 + if SPEC::enabled(CANCUN) { + let data_fee = env.calc_data_fee().expect("already checked"); + gas_cost = gas_cost.saturating_add(data_fee); + } + + // set new caller account balance. + caller_account.info.balance = caller_account.info.balance.saturating_sub(gas_cost); + + // bump the nonce for calls. Nonce for CREATE will be bumped in `handle_create`. + if matches!(env.tx.transact_to, TransactTo::Call(_)) { + // Nonce is already checked + caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); + } + + // touch account so we know it is changed. + caller_account.mark_touch(); +} + +/// Deducts the caller balance to the transaction limit. +#[inline] +pub fn deduct_caller( + context: &mut Context, +) -> Result<(), EVMError> { + // load caller's account. + let (caller_account, _) = context + .evm + .inner + .journaled_state + .load_account(context.evm.inner.env.tx.caller, &mut context.evm.inner.db)?; + + // deduct gas cost from caller's account. + deduct_caller_inner::(caller_account, &context.evm.inner.env); + + Ok(()) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/validation.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/validation.md new file mode 100644 index 00000000..325cc6ca --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/mainnet/validation.md @@ -0,0 +1,61 @@ +# ๐Ÿฆ€ validation.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/mainnet/validation.rs) + +```rust +use revm_interpreter::gas; + +use crate::{ + primitives::{db::Database, EVMError, Env, InvalidTransaction, Spec}, + Context, +}; + +/// Validate environment for the mainnet. +pub fn validate_env(env: &Env) -> Result<(), EVMError> { + // Important: validate block before tx. + env.validate_block_env::()?; + env.validate_tx::()?; + Ok(()) +} + +/// Validates transaction against the state. +pub fn validate_tx_against_state( + context: &mut Context, +) -> Result<(), EVMError> { + // load acc + let tx_caller = context.evm.env.tx.caller; + let (caller_account, _) = context + .evm + .inner + .journaled_state + .load_account(tx_caller, &mut context.evm.inner.db)?; + + context + .evm + .inner + .env + .validate_tx_against_state::(caller_account) + .map_err(EVMError::Transaction)?; + + Ok(()) +} + +/// Validate initial transaction gas. +pub fn validate_initial_tx_gas( + env: &Env, +) -> Result> { + let input = &env.tx.data; + let is_create = env.tx.transact_to.is_create(); + let access_list = &env.tx.access_list; + let initcodes = &env.tx.eof_initcodes; + + let initial_gas_spend = + gas::validate_initial_tx_gas(SPEC::SPEC_ID, input, is_create, access_list, initcodes); + + // Additional check to see if limit is big enough to cover initial gas. + if initial_gas_spend > env.tx.gas_limit { + return Err(InvalidTransaction::CallGasCostMoreThanGasLimit.into()); + } + Ok(initial_gas_spend) +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/handler/register.md b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/register.md new file mode 100644 index 00000000..31506a88 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/handler/register.md @@ -0,0 +1,34 @@ +# ๐Ÿฆ€ register.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/handler/register.rs) + +```rust +use crate::{db::Database, handler::Handler, Evm}; +use std::boxed::Box; + +/// EVM Handler +pub type EvmHandler<'a, EXT, DB> = Handler<'a, Evm<'a, EXT, DB>, EXT, DB>; + +// Handle register +pub type HandleRegister = for<'a> fn(&mut EvmHandler<'a, EXT, DB>); + +// Boxed handle register +pub type HandleRegisterBox = Box Fn(&mut EvmHandler<'a, EXT, DB>)>; + +pub enum HandleRegisters { + /// Plain function register + Plain(HandleRegister), + /// Boxed function register. + Box(HandleRegisterBox), +} + +impl HandleRegisters { + /// Call register function to modify EvmHandler. + pub fn register(&self, handler: &mut EvmHandler<'_, EXT, DB>) { + match self { + HandleRegisters::Plain(f) => f(handler), + HandleRegisters::Box(f) => f(handler), + } + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/inspector.md b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector.md new file mode 100644 index 00000000..a70881ff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector.md @@ -0,0 +1,172 @@ +# ๐Ÿฆ€ inspector.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/inspector.rs) + +```rust +use crate::{ + interpreter::{CallInputs, CreateInputs, EOFCreateInput, EOFCreateOutcome, Interpreter}, + primitives::{db::Database, Address, Log, U256}, + EvmContext, +}; +use auto_impl::auto_impl; + +#[cfg(feature = "std")] +mod customprinter; +#[cfg(all(feature = "std", feature = "serde-json"))] +mod eip3155; +mod gas; +mod handler_register; +mod noop; + +// Exports. + +pub use handler_register::{inspector_handle_register, inspector_instruction, GetInspector}; +use revm_interpreter::{CallOutcome, CreateOutcome}; + +/// [Inspector] implementations. +pub mod inspectors { + #[cfg(feature = "std")] + pub use super::customprinter::CustomPrintTracer; + #[cfg(all(feature = "std", feature = "serde-json"))] + pub use super::eip3155::TracerEip3155; + pub use super::gas::GasInspector; + pub use super::noop::NoOpInspector; +} + +/// EVM [Interpreter] callbacks. +#[auto_impl(&mut, Box)] +pub trait Inspector { + /// Called before the interpreter is initialized. + /// + /// If `interp.instruction_result` is set to anything other than [crate::interpreter::InstructionResult::Continue] then the execution of the interpreter + /// is skipped. + #[inline] + fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + let _ = interp; + let _ = context; + } + + /// Called on each step of the interpreter. + /// + /// Information about the current execution, including the memory, stack and more is available + /// on `interp` (see [Interpreter]). + /// + /// # Example + /// + /// To get the current opcode, use `interp.current_opcode()`. + #[inline] + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + let _ = interp; + let _ = context; + } + + /// Called after `step` when the instruction has been executed. + /// + /// Setting `interp.instruction_result` to anything other than [crate::interpreter::InstructionResult::Continue] alters the execution + /// of the interpreter. + #[inline] + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + let _ = interp; + let _ = context; + } + + /// Called when a log is emitted. + #[inline] + fn log(&mut self, context: &mut EvmContext, log: &Log) { + let _ = context; + let _ = log; + } + + /// Called whenever a call to a contract is about to start. + /// + /// InstructionResulting anything other than [crate::interpreter::InstructionResult::Continue] overrides the result of the call. + #[inline] + fn call( + &mut self, + context: &mut EvmContext, + inputs: &mut CallInputs, + ) -> Option { + let _ = context; + let _ = inputs; + None + } + + /// Called when a call to a contract has concluded. + /// + /// The returned [CallOutcome] is used as the result of the call. + /// + /// This allows the inspector to modify the given `result` before returning it. + #[inline] + fn call_end( + &mut self, + context: &mut EvmContext, + inputs: &CallInputs, + outcome: CallOutcome, + ) -> CallOutcome { + let _ = context; + let _ = inputs; + outcome + } + + /// Called when a contract is about to be created. + /// + /// If this returns `Some` then the [CreateOutcome] is used to override the result of the creation. + /// + /// If this returns `None` then the creation proceeds as normal. + #[inline] + fn create( + &mut self, + context: &mut EvmContext, + inputs: &mut CreateInputs, + ) -> Option { + let _ = context; + let _ = inputs; + None + } + + /// Called when a contract has been created. + /// + /// InstructionResulting anything other than the values passed to this function (`(ret, remaining_gas, + /// address, out)`) will alter the result of the create. + #[inline] + fn create_end( + &mut self, + context: &mut EvmContext, + inputs: &CreateInputs, + outcome: CreateOutcome, + ) -> CreateOutcome { + let _ = context; + let _ = inputs; + outcome + } + + fn eofcreate( + &mut self, + context: &mut EvmContext, + inputs: &mut EOFCreateInput, + ) -> Option { + let _ = context; + let _ = inputs; + None + } + + fn eofcreate_end( + &mut self, + context: &mut EvmContext, + inputs: &EOFCreateInput, + outcome: EOFCreateOutcome, + ) -> EOFCreateOutcome { + let _ = context; + let _ = inputs; + outcome + } + + /// Called when a contract has been self-destructed with funds transferred to target. + #[inline] + fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + let _ = contract; + let _ = target; + let _ = value; + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/customprinter.md b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/customprinter.md new file mode 100644 index 00000000..eb1376dc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/customprinter.md @@ -0,0 +1,160 @@ +# ๐Ÿฆ€ customprinter.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/inspector/customprinter.rs) + +```rust +//! Custom print inspector, it has step level information of execution. +//! It is a great tool if some debugging is needed. + +use revm_interpreter::CallOutcome; +use revm_interpreter::CreateOutcome; +use revm_interpreter::OpCode; + +use crate::{ + inspectors::GasInspector, + interpreter::{CallInputs, CreateInputs, Interpreter}, + primitives::{Address, U256}, + Database, EvmContext, Inspector, +}; + +/// Custom print [Inspector], it has step level information of execution. +/// +/// It is a great tool if some debugging is needed. +#[derive(Clone, Debug, Default)] +pub struct CustomPrintTracer { + gas_inspector: GasInspector, +} + +impl Inspector for CustomPrintTracer { + fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.gas_inspector.initialize_interp(interp, context); + } + + // get opcode by calling `interp.contract.opcode(interp.program_counter())`. + // all other information can be obtained from interp. + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + let opcode = interp.current_opcode(); + let name = OpCode::name_by_op(opcode); + + let gas_remaining = self.gas_inspector.gas_remaining(); + + let memory_size = interp.shared_memory.len(); + + println!( + "depth:{}, PC:{}, gas:{:#x}({}), OPCODE: {:?}({:?}) refund:{:#x}({}) Stack:{:?}, Data size:{}", + context.journaled_state.depth(), + interp.program_counter(), + gas_remaining, + gas_remaining, + name, + opcode, + interp.gas.refunded(), + interp.gas.refunded(), + interp.stack.data(), + memory_size, + ); + + self.gas_inspector.step(interp, context); + } + + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.gas_inspector.step_end(interp, context); + } + + fn call_end( + &mut self, + context: &mut EvmContext, + inputs: &CallInputs, + outcome: CallOutcome, + ) -> CallOutcome { + self.gas_inspector.call_end(context, inputs, outcome) + } + + fn create_end( + &mut self, + context: &mut EvmContext, + inputs: &CreateInputs, + outcome: CreateOutcome, + ) -> CreateOutcome { + self.gas_inspector.create_end(context, inputs, outcome) + } + + fn call( + &mut self, + _context: &mut EvmContext, + inputs: &mut CallInputs, + ) -> Option { + println!( + "SM Address: {:?}, caller:{:?},target:{:?} is_static:{:?}, transfer:{:?}, input_size:{:?}", + inputs.bytecode_address, + inputs.caller, + inputs.target_address, + inputs.is_static, + inputs.value, + inputs.input.len(), + ); + None + } + + fn create( + &mut self, + _context: &mut EvmContext, + inputs: &mut CreateInputs, + ) -> Option { + println!( + "CREATE CALL: caller:{:?}, scheme:{:?}, value:{:?}, init_code:{:?}, gas:{:?}", + inputs.caller, inputs.scheme, inputs.value, inputs.init_code, inputs.gas_limit + ); + None + } + + fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + println!( + "SELFDESTRUCT: contract: {:?}, refund target: {:?}, value {:?}", + contract, target, value + ); + } +} + +#[cfg(test)] +mod test { + use crate::{ + inspector_handle_register, + inspectors::CustomPrintTracer, + primitives::{address, bytes, SpecId}, + Evm, InMemoryDB, + }; + + #[test] + fn gas_calculation_underflow() { + let callee = address!("5fdcca53617f4d2b9134b29090c87d01058e27e9"); + + // https://github.com/bluealloy/revm/issues/277 + // checks this use case + let mut evm = Evm::builder() + .with_db(InMemoryDB::default()) + .modify_db(|db| { + let code = bytes!("5b597fb075978b6c412c64d169d56d839a8fe01b3f4607ed603b2c78917ce8be1430fe6101e8527ffe64706ecad72a2f5c97a95e006e279dc57081902029ce96af7edae5de116fec610208527f9fc1ef09d4dd80683858ae3ea18869fe789ddc365d8d9d800e26c9872bac5e5b6102285260276102485360d461024953601661024a53600e61024b53607d61024c53600961024d53600b61024e5360b761024f5360596102505360796102515360a061025253607261025353603a6102545360fb61025553601261025653602861025753600761025853606f61025953601761025a53606161025b53606061025c5360a661025d53602b61025e53608961025f53607a61026053606461026153608c6102625360806102635360d56102645360826102655360ae61026653607f6101e8610146610220677a814b184591c555735fdcca53617f4d2b9134b29090c87d01058e27e962047654f259595947443b1b816b65cdb6277f4b59c10a36f4e7b8658f5a5e6f5561"); + let info = crate::primitives::AccountInfo { + balance: "0x100c5d668240db8e00".parse().unwrap(), + code_hash: crate::primitives::keccak256(&code), + code: Some(crate::primitives::Bytecode::new_raw(code.clone())), + nonce: 1, + }; + db.insert_account_info(callee, info); + }) + .modify_tx_env(|tx| { + tx.caller = address!("5fdcca53617f4d2b9134b29090c87d01058e27e0"); + tx.transact_to = crate::primitives::TransactTo::Call(callee); + tx.data = crate::primitives::Bytes::new(); + tx.value = crate::primitives::U256::ZERO; + }) + .with_external_context(CustomPrintTracer::default()) + .with_spec_id(SpecId::BERLIN) + .append_handler_register(inspector_handle_register) + .build(); + + evm.transact().expect("Transaction to work"); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/eip3155.md b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/eip3155.md new file mode 100644 index 00000000..7d43bcdc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/eip3155.md @@ -0,0 +1,292 @@ +# ๐Ÿฆ€ eip3155.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/inspector/eip3155.rs) + +```rust +use crate::{ + inspectors::GasInspector, + interpreter::{ + CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter, InterpreterResult, + }, + primitives::{db::Database, hex, HashMap, B256, U256}, + EvmContext, Inspector, +}; +use revm_interpreter::OpCode; +use serde::Serialize; +use std::io::Write; + +/// [EIP-3155](https://eips.ethereum.org/EIPS/eip-3155) tracer [Inspector]. +pub struct TracerEip3155 { + output: Box, + gas_inspector: GasInspector, + + /// Print summary of the execution. + print_summary: bool, + + stack: Vec, + pc: usize, + opcode: u8, + gas: u64, + refunded: i64, + mem_size: usize, + skip: bool, + include_memory: bool, + memory: Option, +} + +// # Output +// The CUT MUST output a `json` object for EACH operation. +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct Output { + // Required fields: + /// Program counter + pc: u64, + /// OpCode + op: u8, + /// Gas left before executing this operation + gas: String, + /// Gas cost of this operation + gas_cost: String, + /// Array of all values on the stack + stack: Vec, + /// Depth of the call stack + depth: u64, + /// Data returned by the function call + return_data: String, + /// Amount of **global** gas refunded + refund: String, + /// Size of memory array + mem_size: String, + + // Optional fields: + /// Name of the operation + #[serde(default, skip_serializing_if = "Option::is_none")] + op_name: Option<&'static str>, + /// Description of an error (should contain revert reason if supported) + #[serde(default, skip_serializing_if = "Option::is_none")] + error: Option, + /// Array of all allocated values + #[serde(default, skip_serializing_if = "Option::is_none")] + memory: Option, + /// Array of all stored values + #[serde(default, skip_serializing_if = "Option::is_none")] + storage: Option>, + /// Array of values, Stack of the called function + #[serde(default, skip_serializing_if = "Option::is_none")] + return_stack: Option>, +} + +// # Summary and error handling +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct Summary { + // Required fields: + /// Root of the state trie after executing the transaction + state_root: String, + /// Return values of the function + output: String, + /// All gas used by the transaction + gas_used: String, + /// Bool whether transaction was executed successfully + pass: bool, + + // Optional fields: + /// Time in nanoseconds needed to execute the transaction + #[serde(default, skip_serializing_if = "Option::is_none")] + time: Option, + /// Name of the fork rules used for execution + #[serde(default, skip_serializing_if = "Option::is_none")] + fork: Option, +} + +impl TracerEip3155 { + /// Sets the writer to use for the output. + pub fn set_writer(&mut self, writer: Box) { + self.output = writer; + } + + /// Resets the Tracer to its initial state of [Self::new]. + /// This makes the inspector ready to be used again. + pub fn clear(&mut self) { + let Self { + gas_inspector, + stack, + pc, + opcode, + gas, + refunded, + mem_size, + skip, + .. + } = self; + *gas_inspector = GasInspector::default(); + stack.clear(); + *pc = 0; + *opcode = 0; + *gas = 0; + *refunded = 0; + *mem_size = 0; + *skip = false; + } +} + +impl TracerEip3155 { + pub fn new(output: Box) -> Self { + Self { + output, + gas_inspector: GasInspector::default(), + print_summary: true, + include_memory: false, + stack: Default::default(), + memory: Default::default(), + pc: 0, + opcode: 0, + gas: 0, + refunded: 0, + mem_size: 0, + skip: false, + } + } + + /// Don't include a summary at the end of the trace + pub fn without_summary(mut self) -> Self { + self.print_summary = false; + self + } + + /// Include a memory field for each step. This significantly increases processing time and output size. + pub fn with_memory(mut self) -> Self { + self.include_memory = true; + self + } + + fn write_value(&mut self, value: &impl serde::Serialize) -> std::io::Result<()> { + serde_json::to_writer(&mut *self.output, value)?; + self.output.write_all(b"\n")?; + self.output.flush() + } + + fn print_summary( + &mut self, + result: &InterpreterResult, + context: &mut EvmContext, + ) { + if self.print_summary { + let spec_name: &str = context.spec_id().into(); + let value = Summary { + state_root: B256::ZERO.to_string(), + output: result.output.to_string(), + gas_used: hex_number( + context.inner.env().tx.gas_limit - self.gas_inspector.gas_remaining(), + ), + pass: result.is_ok(), + time: None, + fork: Some(spec_name.to_string()), + }; + let _ = self.write_value(&value); + } + } +} + +impl Inspector for TracerEip3155 { + fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.gas_inspector.initialize_interp(interp, context); + } + + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.gas_inspector.step(interp, context); + self.stack = interp.stack.data().clone(); + self.memory = if self.include_memory { + Some(hex::encode_prefixed(interp.shared_memory.context_memory())) + } else { + None + }; + self.pc = interp.program_counter(); + self.opcode = interp.current_opcode(); + self.mem_size = interp.shared_memory.len(); + self.gas = interp.gas.remaining(); + self.refunded = interp.gas.refunded(); + } + + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.gas_inspector.step_end(interp, context); + if self.skip { + self.skip = false; + return; + } + + let value = Output { + pc: self.pc as u64, + op: self.opcode, + gas: hex_number(self.gas), + gas_cost: hex_number(self.gas_inspector.last_gas_cost()), + stack: self.stack.iter().map(hex_number_u256).collect(), + depth: context.journaled_state.depth(), + return_data: "0x".to_string(), + refund: hex_number(self.refunded as u64), + mem_size: self.mem_size.to_string(), + + op_name: OpCode::new(self.opcode).map(|i| i.as_str()), + error: if !interp.instruction_result.is_ok() { + Some(format!("{:?}", interp.instruction_result)) + } else { + None + }, + memory: self.memory.take(), + storage: None, + return_stack: None, + }; + let _ = self.write_value(&value); + } + + fn call_end( + &mut self, + context: &mut EvmContext, + inputs: &CallInputs, + outcome: CallOutcome, + ) -> CallOutcome { + let outcome = self.gas_inspector.call_end(context, inputs, outcome); + + if context.journaled_state.depth() == 0 { + self.print_summary(&outcome.result, context); + // clear the state if we are at the top level + self.clear(); + } + + outcome + } + + fn create_end( + &mut self, + context: &mut EvmContext, + inputs: &CreateInputs, + outcome: CreateOutcome, + ) -> CreateOutcome { + let outcome = self.gas_inspector.create_end(context, inputs, outcome); + + if context.journaled_state.depth() == 0 { + self.print_summary(&outcome.result, context); + + // clear the state if we are at the top level + self.clear(); + } + + outcome + } +} + +fn hex_number(uint: u64) -> String { + format!("0x{uint:x}") +} + +fn hex_number_u256(b: &U256) -> String { + let s = hex::encode(b.to_be_bytes::<32>()); + let s = s.trim_start_matches('0'); + if s.is_empty() { + "0x0".to_string() + } else { + format!("0x{s}") + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/gas.md b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/gas.md new file mode 100644 index 00000000..fd56a7f8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/gas.md @@ -0,0 +1,226 @@ +# ๐Ÿฆ€ gas.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/inspector/gas.rs) + +```rust +//! GasIspector. Helper Inspector to calculate gas for others. + +use revm_interpreter::CallOutcome; + +use crate::{ + interpreter::{CallInputs, CreateInputs, CreateOutcome}, + primitives::db::Database, + EvmContext, Inspector, +}; + +/// Helper [Inspector] that keeps track of gas. +#[allow(dead_code)] +#[derive(Clone, Copy, Debug, Default)] +pub struct GasInspector { + gas_remaining: u64, + last_gas_cost: u64, +} + +impl GasInspector { + pub fn gas_remaining(&self) -> u64 { + self.gas_remaining + } + + pub fn last_gas_cost(&self) -> u64 { + self.last_gas_cost + } +} + +impl Inspector for GasInspector { + fn initialize_interp( + &mut self, + interp: &mut crate::interpreter::Interpreter, + _context: &mut EvmContext, + ) { + self.gas_remaining = interp.gas.limit(); + } + + fn step( + &mut self, + interp: &mut crate::interpreter::Interpreter, + _context: &mut EvmContext, + ) { + self.gas_remaining = interp.gas.remaining(); + } + + fn step_end( + &mut self, + interp: &mut crate::interpreter::Interpreter, + _context: &mut EvmContext, + ) { + let remaining = interp.gas.remaining(); + self.last_gas_cost = self.gas_remaining.saturating_sub(remaining); + self.gas_remaining = remaining; + } + + fn call_end( + &mut self, + _context: &mut EvmContext, + _inputs: &CallInputs, + mut outcome: CallOutcome, + ) -> CallOutcome { + if outcome.result.result.is_error() { + outcome.result.gas.spend_all(); + self.gas_remaining = 0; + } + outcome + } + + fn create_end( + &mut self, + _context: &mut EvmContext, + _inputs: &CreateInputs, + mut outcome: CreateOutcome, + ) -> CreateOutcome { + if outcome.result.result.is_error() { + outcome.result.gas.spend_all(); + self.gas_remaining = 0; + } + outcome + } +} + +#[cfg(test)] +mod tests { + + use revm_interpreter::CallOutcome; + use revm_interpreter::CreateOutcome; + + use crate::{ + inspectors::GasInspector, + interpreter::{CallInputs, CreateInputs, Interpreter}, + primitives::Log, + Database, EvmContext, Inspector, + }; + + #[derive(Default, Debug)] + struct StackInspector { + pc: usize, + gas_inspector: GasInspector, + gas_remaining_steps: Vec<(usize, u64)>, + } + + impl Inspector for StackInspector { + fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.gas_inspector.initialize_interp(interp, context); + } + + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.pc = interp.program_counter(); + self.gas_inspector.step(interp, context); + } + + fn log(&mut self, context: &mut EvmContext, log: &Log) { + self.gas_inspector.log(context, log); + } + + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + self.gas_inspector.step_end(interp, context); + self.gas_remaining_steps + .push((self.pc, self.gas_inspector.gas_remaining())); + } + + fn call( + &mut self, + context: &mut EvmContext, + call: &mut CallInputs, + ) -> Option { + self.gas_inspector.call(context, call) + } + + fn call_end( + &mut self, + context: &mut EvmContext, + inputs: &CallInputs, + outcome: CallOutcome, + ) -> CallOutcome { + self.gas_inspector.call_end(context, inputs, outcome) + } + + fn create( + &mut self, + context: &mut EvmContext, + call: &mut CreateInputs, + ) -> Option { + self.gas_inspector.create(context, call); + None + } + + fn create_end( + &mut self, + context: &mut EvmContext, + inputs: &CreateInputs, + outcome: CreateOutcome, + ) -> CreateOutcome { + self.gas_inspector.create_end(context, inputs, outcome) + } + } + + #[test] + fn test_gas_inspector() { + use crate::{ + db::BenchmarkDB, + inspector::inspector_handle_register, + interpreter::opcode, + primitives::{address, Bytecode, Bytes, TransactTo}, + Evm, + }; + + let contract_data: Bytes = Bytes::from(vec![ + opcode::PUSH1, + 0x1, + opcode::PUSH1, + 0xb, + opcode::JUMPI, + opcode::PUSH1, + 0x1, + opcode::PUSH1, + 0x1, + opcode::PUSH1, + 0x1, + opcode::JUMPDEST, + opcode::STOP, + ]); + let bytecode = Bytecode::new_raw(contract_data); + + let mut evm: Evm<'_, StackInspector, BenchmarkDB> = Evm::builder() + .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) + .with_external_context(StackInspector::default()) + .modify_tx_env(|tx| { + tx.clear(); + tx.caller = address!("1000000000000000000000000000000000000000"); + tx.transact_to = + TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.gas_limit = 21100; + }) + .append_handler_register(inspector_handle_register) + .build(); + + // run evm. + evm.transact().unwrap(); + + let inspector = evm.into_context().external; + + // starting from 100gas + let steps = vec![ + // push1 -3 + (0, 97), + // push1 -3 + (2, 94), + // jumpi -10 + (4, 84), + // jumpdest 1 + (11, 83), + // stop 0 + (12, 83), + ]; + + assert_eq!(inspector.gas_remaining_steps, steps); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/handler_register.md b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/handler_register.md new file mode 100644 index 00000000..5d6759a3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/handler_register.md @@ -0,0 +1,431 @@ +# ๐Ÿฆ€ handler_register.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/inspector/handler_register.rs) + +```rust +use crate::{ + db::Database, + handler::register::EvmHandler, + interpreter::{opcode, opcode::BoxedInstruction, InstructionResult, Interpreter}, + primitives::EVMError, + Evm, FrameOrResult, FrameResult, Inspector, JournalEntry, +}; +use core::cell::RefCell; +use revm_interpreter::opcode::InstructionTables; +use std::{boxed::Box, rc::Rc, sync::Arc, vec::Vec}; + +/// Provides access to an `Inspector` instance. +pub trait GetInspector { + /// Returns the associated `Inspector`. + fn get_inspector(&mut self) -> &mut impl Inspector; +} + +impl> GetInspector for INSP { + #[inline] + fn get_inspector(&mut self) -> &mut impl Inspector { + self + } +} + +/// Register Inspector handles that interact with Inspector instance. +/// +/// +/// # Note +/// +/// Inspector handle register does not override any existing handlers, and it +/// calls them before (or after) calling Inspector. This means that it is safe +/// to use this register with any other register. +/// +/// A few instructions handlers are wrapped twice once for `step` and `step_end` +/// and in case of Logs and Selfdestruct wrapper is wrapped again for the +/// `log` and `selfdestruct` calls. +pub fn inspector_handle_register<'a, DB: Database, EXT: GetInspector>( + handler: &mut EvmHandler<'a, EXT, DB>, +) { + // Every instruction inside flat table that is going to be wrapped by inspector calls. + let table = handler + .take_instruction_table() + .expect("Handler must have instruction table"); + let mut table = match table { + InstructionTables::Plain(table) => table + .into_iter() + .map(|i| inspector_instruction(i)) + .collect::>(), + InstructionTables::Boxed(table) => table + .into_iter() + .map(|i| inspector_instruction(i)) + .collect::>(), + }; + + // Register inspector Log instruction. + let mut inspect_log = |index: u8| { + if let Some(i) = table.get_mut(index as usize) { + let old = core::mem::replace(i, Box::new(|_, _| ())); + *i = Box::new( + move |interpreter: &mut Interpreter, host: &mut Evm<'a, EXT, DB>| { + let old_log_len = host.context.evm.journaled_state.logs.len(); + old(interpreter, host); + // check if log was added. It is possible that revert happened + // cause of gas or stack underflow. + if host.context.evm.journaled_state.logs.len() == old_log_len + 1 { + // clone log. + // TODO decide if we should remove this and leave the comment + // that log can be found as journaled_state. + let last_log = host + .context + .evm + .journaled_state + .logs + .last() + .unwrap() + .clone(); + // call Inspector + host.context + .external + .get_inspector() + .log(&mut host.context.evm, &last_log); + } + }, + ) + } + }; + + inspect_log(opcode::LOG0); + inspect_log(opcode::LOG1); + inspect_log(opcode::LOG2); + inspect_log(opcode::LOG3); + inspect_log(opcode::LOG4); + + // // register selfdestruct function. + if let Some(i) = table.get_mut(opcode::SELFDESTRUCT as usize) { + let old = core::mem::replace(i, Box::new(|_, _| ())); + *i = Box::new( + move |interpreter: &mut Interpreter, host: &mut Evm<'a, EXT, DB>| { + // execute selfdestruct + old(interpreter, host); + // check if selfdestruct was successful and if journal entry is made. + if let Some(JournalEntry::AccountDestroyed { + address, + target, + had_balance, + .. + }) = host + .context + .evm + .journaled_state + .journal + .last() + .unwrap() + .last() + { + host.context.external.get_inspector().selfdestruct( + *address, + *target, + *had_balance, + ); + } + }, + ) + } + + // cast vector to array. + handler.set_instruction_table(InstructionTables::Boxed( + table.try_into().unwrap_or_else(|_| unreachable!()), + )); + + // call and create input stack shared between handlers. They are used to share + // inputs in *_end Inspector calls. + let call_input_stack = Rc::>>::new(RefCell::new(Vec::new())); + let create_input_stack = Rc::>>::new(RefCell::new(Vec::new())); + let eofcreate_input_stack = Rc::>>::new(RefCell::new(Vec::new())); + + // Create handler + let create_input_stack_inner = create_input_stack.clone(); + let old_handle = handler.execution.create.clone(); + handler.execution.create = Arc::new( + move |ctx, mut inputs| -> Result> { + let inspector = ctx.external.get_inspector(); + // call inspector create to change input or return outcome. + if let Some(outcome) = inspector.create(&mut ctx.evm, &mut inputs) { + create_input_stack_inner.borrow_mut().push(inputs.clone()); + return Ok(FrameOrResult::Result(FrameResult::Create(outcome))); + } + create_input_stack_inner.borrow_mut().push(inputs.clone()); + + let mut frame_or_result = old_handle(ctx, inputs); + if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { + ctx.external + .get_inspector() + .initialize_interp(frame.interpreter_mut(), &mut ctx.evm) + } + frame_or_result + }, + ); + + // Call handler + let call_input_stack_inner = call_input_stack.clone(); + let old_handle = handler.execution.call.clone(); + handler.execution.call = Arc::new( + move |ctx, mut inputs| -> Result> { + // Call inspector to change input or return outcome. + let outcome = ctx.external.get_inspector().call(&mut ctx.evm, &mut inputs); + call_input_stack_inner.borrow_mut().push(inputs.clone()); + if let Some(outcome) = outcome { + return Ok(FrameOrResult::Result(FrameResult::Call(outcome))); + } + + let mut frame_or_result = old_handle(ctx, inputs); + if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { + ctx.external + .get_inspector() + .initialize_interp(frame.interpreter_mut(), &mut ctx.evm) + } + frame_or_result + }, + ); + + // TODO(EOF) EOF create call. + + // call outcome + let call_input_stack_inner = call_input_stack.clone(); + let old_handle = handler.execution.insert_call_outcome.clone(); + handler.execution.insert_call_outcome = + Arc::new(move |ctx, frame, shared_memory, mut outcome| { + let call_inputs = call_input_stack_inner.borrow_mut().pop().unwrap(); + outcome = ctx + .external + .get_inspector() + .call_end(&mut ctx.evm, &call_inputs, outcome); + old_handle(ctx, frame, shared_memory, outcome) + }); + + // create outcome + let create_input_stack_inner = create_input_stack.clone(); + let old_handle = handler.execution.insert_create_outcome.clone(); + handler.execution.insert_create_outcome = Arc::new(move |ctx, frame, mut outcome| { + let create_inputs = create_input_stack_inner.borrow_mut().pop().unwrap(); + outcome = ctx + .external + .get_inspector() + .create_end(&mut ctx.evm, &create_inputs, outcome); + old_handle(ctx, frame, outcome) + }); + + // TODO(EOF) EOF create handle. + + // last frame outcome + let old_handle = handler.execution.last_frame_return.clone(); + handler.execution.last_frame_return = Arc::new(move |ctx, frame_result| { + let inspector = ctx.external.get_inspector(); + match frame_result { + FrameResult::Call(outcome) => { + let call_inputs = call_input_stack.borrow_mut().pop().unwrap(); + *outcome = inspector.call_end(&mut ctx.evm, &call_inputs, outcome.clone()); + } + FrameResult::Create(outcome) => { + let create_inputs = create_input_stack.borrow_mut().pop().unwrap(); + *outcome = inspector.create_end(&mut ctx.evm, &create_inputs, outcome.clone()); + } + FrameResult::EOFCreate(outcome) => { + let eofcreate_inputs = eofcreate_input_stack.borrow_mut().pop().unwrap(); + *outcome = + inspector.eofcreate_end(&mut ctx.evm, &eofcreate_inputs, outcome.clone()); + } + } + old_handle(ctx, frame_result) + }); +} + +/// Outer closure that calls Inspector for every instruction. +pub fn inspector_instruction< + 'a, + INSP: GetInspector, + DB: Database, + Instruction: Fn(&mut Interpreter, &mut Evm<'a, INSP, DB>) + 'a, +>( + instruction: Instruction, +) -> BoxedInstruction<'a, Evm<'a, INSP, DB>> { + Box::new( + move |interpreter: &mut Interpreter, host: &mut Evm<'a, INSP, DB>| { + // SAFETY: as the PC was already incremented we need to subtract 1 to preserve the + // old Inspector behavior. + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.sub(1) }; + + host.context + .external + .get_inspector() + .step(interpreter, &mut host.context.evm); + if interpreter.instruction_result != InstructionResult::Continue { + return; + } + + // return PC to old value + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.add(1) }; + + // execute instruction. + instruction(interpreter, host); + + host.context + .external + .get_inspector() + .step_end(interpreter, &mut host.context.evm); + }, + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + db::EmptyDB, + inspectors::NoOpInspector, + interpreter::{opcode::*, CallInputs, CallOutcome, CreateInputs, CreateOutcome}, + primitives::BerlinSpec, + EvmContext, + }; + + // Test that this pattern builds. + #[test] + fn test_make_boxed_instruction_table() { + type MyEvm<'a> = Evm<'a, NoOpInspector, EmptyDB>; + let table: InstructionTable> = make_instruction_table::, BerlinSpec>(); + let _boxed_table: BoxedInstructionTable<'_, MyEvm<'_>> = + make_boxed_instruction_table::<'_, MyEvm<'_>, BerlinSpec, _>( + table, + inspector_instruction, + ); + } + + #[derive(Default, Debug)] + struct StackInspector { + initialize_interp_called: bool, + step: u32, + step_end: u32, + call: bool, + call_end: bool, + } + + impl Inspector for StackInspector { + fn initialize_interp(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { + if self.initialize_interp_called { + unreachable!("initialize_interp should not be called twice") + } + self.initialize_interp_called = true; + } + + fn step(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { + self.step += 1; + } + + fn step_end(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { + self.step_end += 1; + } + + fn call( + &mut self, + context: &mut EvmContext, + _call: &mut CallInputs, + ) -> Option { + if self.call { + unreachable!("call should not be called twice") + } + self.call = true; + assert_eq!(context.journaled_state.depth(), 0); + None + } + + fn call_end( + &mut self, + context: &mut EvmContext, + _inputs: &CallInputs, + outcome: CallOutcome, + ) -> CallOutcome { + if self.call_end { + unreachable!("call_end should not be called twice") + } + assert_eq!(context.journaled_state.depth(), 0); + self.call_end = true; + outcome + } + + fn create( + &mut self, + context: &mut EvmContext, + _call: &mut CreateInputs, + ) -> Option { + assert_eq!(context.journaled_state.depth(), 0); + None + } + + fn create_end( + &mut self, + context: &mut EvmContext, + _inputs: &CreateInputs, + outcome: CreateOutcome, + ) -> CreateOutcome { + assert_eq!(context.journaled_state.depth(), 0); + outcome + } + } + + #[test] + fn test_inspector_handlers() { + use crate::{ + db::BenchmarkDB, + inspector::inspector_handle_register, + interpreter::opcode, + primitives::{address, Bytecode, Bytes, TransactTo}, + Evm, + }; + + let contract_data: Bytes = Bytes::from(vec![ + opcode::PUSH1, + 0x1, + opcode::PUSH1, + 0xb, + opcode::PUSH1, + 0x1, + opcode::PUSH1, + 0x1, + opcode::PUSH1, + 0x1, + opcode::CREATE, + opcode::STOP, + ]); + let bytecode = Bytecode::new_raw(contract_data); + + let mut evm: Evm<'_, StackInspector, BenchmarkDB> = Evm::builder() + .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) + .with_external_context(StackInspector::default()) + .modify_tx_env(|tx| { + tx.clear(); + tx.caller = address!("1000000000000000000000000000000000000000"); + tx.transact_to = + TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.gas_limit = 21100; + }) + .append_handler_register(inspector_handle_register) + .build(); + + // run evm. + evm.transact().unwrap(); + + let inspector = evm.into_context().external; + + assert_eq!(inspector.step, 6); + assert_eq!(inspector.step_end, 6); + assert!(inspector.initialize_interp_called); + assert!(inspector.call); + assert!(inspector.call_end); + } + + #[test] + fn test_inspector_reg() { + let mut noop = NoOpInspector; + let _evm = Evm::builder() + .with_external_context(&mut noop) + .append_handler_register(inspector_handle_register) + .build(); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/noop.md b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/noop.md new file mode 100644 index 00000000..3335e119 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/inspector/noop.md @@ -0,0 +1,12 @@ +# ๐Ÿฆ€ noop.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/inspector/noop.rs) + +```rust +use crate::{Database, Inspector}; +/// Dummy [Inspector], helpful as standalone replacement. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct NoOpInspector; + +impl Inspector for NoOpInspector {} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/journaled_state.md b/docs/revm-python-spec/revm-verif/revm/revm/src/journaled_state.md new file mode 100644 index 00000000..6ac3cadb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/journaled_state.md @@ -0,0 +1,855 @@ +# ๐Ÿฆ€ journaled_state.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/journaled_state.rs) + +```rust +use crate::interpreter::{InstructionResult, SelfDestructResult}; +use crate::primitives::{ + db::Database, hash_map::Entry, Account, Address, Bytecode, EVMError, HashMap, HashSet, Log, + SpecId::*, State, StorageSlot, TransientStorage, KECCAK_EMPTY, PRECOMPILE3, U256, +}; +use core::mem; +use revm_interpreter::primitives::SpecId; +use revm_interpreter::{LoadAccountResult, SStoreResult}; +use std::vec::Vec; + +/// JournalState is internal EVM state that is used to contain state and track changes to that state. +/// It contains journal of changes that happened to state so that they can be reverted. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct JournaledState { + /// Current state. + pub state: State, + /// [EIP-1153[(https://eips.ethereum.org/EIPS/eip-1153) transient storage that is discarded after every transactions + pub transient_storage: TransientStorage, + /// logs + pub logs: Vec, + /// how deep are we in call stack. + pub depth: usize, + /// journal with changes that happened between calls. + pub journal: Vec>, + /// Ethereum before EIP-161 differently defined empty and not-existing account + /// Spec is needed for two things SpuriousDragon's `EIP-161 State clear`, + /// and for Cancun's `EIP-6780: SELFDESTRUCT in same transaction` + pub spec: SpecId, + /// Warm loaded addresses are used to check if loaded address + /// should be considered cold or warm loaded when the account + /// is first accessed. + /// + /// Note that this not include newly loaded accounts, account and storage + /// is considered warm if it is found in the `State`. + pub warm_preloaded_addresses: HashSet
, +} + +impl JournaledState { + /// Create new JournaledState. + /// + /// warm_preloaded_addresses is used to determine if address is considered warm loaded. + /// In ordinary case this is precompile or beneficiary. + /// + /// Note: This function will journal state after Spurious Dragon fork. + /// And will not take into account if account is not existing or empty. + /// + /// # Note + /// + /// + pub fn new(spec: SpecId, warm_preloaded_addresses: HashSet
) -> JournaledState { + Self { + state: HashMap::new(), + transient_storage: TransientStorage::default(), + logs: Vec::new(), + journal: vec![vec![]], + depth: 0, + spec, + warm_preloaded_addresses, + } + } + + /// Return reference to state. + #[inline] + pub fn state(&mut self) -> &mut State { + &mut self.state + } + + /// Sets SpecId. + #[inline] + pub fn set_spec_id(&mut self, spec: SpecId) { + self.spec = spec; + } + + /// Mark account as touched as only touched accounts will be added to state. + /// This is especially important for state clear where touched empty accounts needs to + /// be removed from state. + #[inline] + pub fn touch(&mut self, address: &Address) { + if let Some(account) = self.state.get_mut(address) { + Self::touch_account(self.journal.last_mut().unwrap(), address, account); + } + } + + /// Mark account as touched. + #[inline] + fn touch_account(journal: &mut Vec, address: &Address, account: &mut Account) { + if !account.is_touched() { + journal.push(JournalEntry::AccountTouched { address: *address }); + account.mark_touch(); + } + } + + /// Clears the JournaledState. Preserving only the spec. + pub fn clear(&mut self) { + let spec = self.spec; + *self = Self::new(spec, HashSet::new()); + } + + /// Does cleanup and returns modified state. + /// + /// This resets the [JournaledState] to its initial state in [Self::new] + #[inline] + pub fn finalize(&mut self) -> (State, Vec) { + let Self { + state, + transient_storage, + logs, + depth, + journal, + // kept, see [Self::new] + spec: _, + warm_preloaded_addresses: _, + } = self; + + *transient_storage = TransientStorage::default(); + *journal = vec![vec![]]; + *depth = 0; + let state = mem::take(state); + let logs = mem::take(logs); + + (state, logs) + } + + /// Returns the _loaded_ [Account] for the given address. + /// + /// This assumes that the account has already been loaded. + /// + /// # Panics + /// + /// Panics if the account has not been loaded and is missing from the state set. + #[inline] + pub fn account(&self, address: Address) -> &Account { + self.state + .get(&address) + .expect("Account expected to be loaded") // Always assume that acc is already loaded + } + + /// Returns call depth. + #[inline] + pub fn depth(&self) -> u64 { + self.depth as u64 + } + + /// use it only if you know that acc is warm + /// Assume account is warm + #[inline] + pub fn set_code(&mut self, address: Address, code: Bytecode) { + let account = self.state.get_mut(&address).unwrap(); + Self::touch_account(self.journal.last_mut().unwrap(), &address, account); + + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::CodeChange { address }); + + account.info.code_hash = code.hash_slow(); + account.info.code = Some(code); + } + + #[inline] + pub fn inc_nonce(&mut self, address: Address) -> Option { + let account = self.state.get_mut(&address).unwrap(); + // Check if nonce is going to overflow. + if account.info.nonce == u64::MAX { + return None; + } + Self::touch_account(self.journal.last_mut().unwrap(), &address, account); + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::NonceChange { address }); + + account.info.nonce += 1; + + Some(account.info.nonce) + } + + /// Transfers balance from two accounts. Returns error if sender balance is not enough. + #[inline] + pub fn transfer( + &mut self, + from: &Address, + to: &Address, + balance: U256, + db: &mut DB, + ) -> Result, EVMError> { + // load accounts + self.load_account(*from, db)?; + self.load_account(*to, db)?; + + // sub balance from + let from_account = &mut self.state.get_mut(from).unwrap(); + Self::touch_account(self.journal.last_mut().unwrap(), from, from_account); + let from_balance = &mut from_account.info.balance; + + let Some(from_balance_incr) = from_balance.checked_sub(balance) else { + return Ok(Some(InstructionResult::OutOfFunds)); + }; + *from_balance = from_balance_incr; + + // add balance to + let to_account = &mut self.state.get_mut(to).unwrap(); + Self::touch_account(self.journal.last_mut().unwrap(), to, to_account); + let to_balance = &mut to_account.info.balance; + let Some(to_balance_decr) = to_balance.checked_add(balance) else { + return Ok(Some(InstructionResult::OverflowPayment)); + }; + *to_balance = to_balance_decr; + // Overflow of U256 balance is not possible to happen on mainnet. We don't bother to return funds from from_acc. + + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::BalanceTransfer { + from: *from, + to: *to, + balance, + }); + + Ok(None) + } + + /// Create account or return false if collision is detected. + /// + /// There are few steps done: + /// 1. Make created account warm loaded (AccessList) and this should + /// be done before subroutine checkpoint is created. + /// 2. Check if there is collision of newly created account with existing one. + /// 3. Mark created account as created. + /// 4. Add fund to created account + /// 5. Increment nonce of created account if SpuriousDragon is active + /// 6. Decrease balance of caller account. + /// + /// # Panics + /// + /// Panics if the caller is not loaded inside of the EVM state. + /// This is should have been done inside `create_inner`. + #[inline] + pub fn create_account_checkpoint( + &mut self, + caller: Address, + address: Address, + balance: U256, + spec_id: SpecId, + ) -> Result { + // Enter subroutine + let checkpoint = self.checkpoint(); + + // Newly created account is present, as we just loaded it. + let account = self.state.get_mut(&address).unwrap(); + let last_journal = self.journal.last_mut().unwrap(); + + // New account can be created if: + // Bytecode is not empty. + // Nonce is not zero + // Account is not precompile. + if account.info.code_hash != KECCAK_EMPTY + || account.info.nonce != 0 + || self.warm_preloaded_addresses.contains(&address) + { + self.checkpoint_revert(checkpoint); + return Err(InstructionResult::CreateCollision); + } + + // set account status to created. + account.mark_created(); + + // this entry will revert set nonce. + last_journal.push(JournalEntry::AccountCreated { address }); + account.info.code = None; + + // Set all storages to default value. They need to be present to act as accessed slots in access list. + // it shouldn't be possible for them to have different values then zero as code is not existing for this account, + // but because tests can change that assumption we are doing it. + let empty = StorageSlot::default(); + account + .storage + .iter_mut() + .for_each(|(_, slot)| *slot = empty.clone()); + + // touch account. This is important as for pre SpuriousDragon account could be + // saved even empty. + Self::touch_account(last_journal, &address, account); + + // Add balance to created account, as we already have target here. + let Some(new_balance) = account.info.balance.checked_add(balance) else { + self.checkpoint_revert(checkpoint); + return Err(InstructionResult::OverflowPayment); + }; + account.info.balance = new_balance; + + // EIP-161: State trie clearing (invariant-preserving alternative) + if spec_id.is_enabled_in(SPURIOUS_DRAGON) { + // nonce is going to be reset to zero in AccountCreated journal entry. + account.info.nonce = 1; + } + + // Sub balance from caller + let caller_account = self.state.get_mut(&caller).unwrap(); + // Balance is already checked in `create_inner`, so it is safe to just subtract. + caller_account.info.balance -= balance; + + // add journal entry of transferred balance + last_journal.push(JournalEntry::BalanceTransfer { + from: caller, + to: address, + balance, + }); + + Ok(checkpoint) + } + + /// Revert all changes that happened in given journal entries. + #[inline] + fn journal_revert( + state: &mut State, + transient_storage: &mut TransientStorage, + journal_entries: Vec, + is_spurious_dragon_enabled: bool, + ) { + for entry in journal_entries.into_iter().rev() { + match entry { + JournalEntry::AccountLoaded { address } => { + state.remove(&address); + } + JournalEntry::AccountTouched { address } => { + if is_spurious_dragon_enabled && address == PRECOMPILE3 { + continue; + } + // remove touched status + state.get_mut(&address).unwrap().unmark_touch(); + } + JournalEntry::AccountDestroyed { + address, + target, + was_destroyed, + had_balance, + } => { + let account = state.get_mut(&address).unwrap(); + // set previous state of selfdestructed flag, as there could be multiple + // selfdestructs in one transaction. + if was_destroyed { + // flag is still selfdestructed + account.mark_selfdestruct(); + } else { + // flag that is not selfdestructed + account.unmark_selfdestruct(); + } + account.info.balance += had_balance; + + if address != target { + let target = state.get_mut(&target).unwrap(); + target.info.balance -= had_balance; + } + } + JournalEntry::BalanceTransfer { from, to, balance } => { + // we don't need to check overflow and underflow when adding and subtracting the balance. + let from = state.get_mut(&from).unwrap(); + from.info.balance += balance; + let to = state.get_mut(&to).unwrap(); + to.info.balance -= balance; + } + JournalEntry::NonceChange { address } => { + state.get_mut(&address).unwrap().info.nonce -= 1; + } + JournalEntry::AccountCreated { address } => { + let account = &mut state.get_mut(&address).unwrap(); + account.unmark_created(); + account.info.nonce = 0; + } + JournalEntry::StorageChange { + address, + key, + had_value, + } => { + let storage = &mut state.get_mut(&address).unwrap().storage; + if let Some(had_value) = had_value { + storage.get_mut(&key).unwrap().present_value = had_value; + } else { + storage.remove(&key); + } + } + JournalEntry::TransientStorageChange { + address, + key, + had_value, + } => { + let tkey = (address, key); + if had_value == U256::ZERO { + // if previous value is zero, remove it + transient_storage.remove(&tkey); + } else { + // if not zero, reinsert old value to transient storage. + transient_storage.insert(tkey, had_value); + } + } + JournalEntry::CodeChange { address } => { + let acc = state.get_mut(&address).unwrap(); + acc.info.code_hash = KECCAK_EMPTY; + acc.info.code = None; + } + } + } + } + + /// Makes a checkpoint that in case of Revert can bring back state to this point. + #[inline] + pub fn checkpoint(&mut self) -> JournalCheckpoint { + let checkpoint = JournalCheckpoint { + log_i: self.logs.len(), + journal_i: self.journal.len(), + }; + self.depth += 1; + self.journal.push(Default::default()); + checkpoint + } + + /// Commit the checkpoint. + #[inline] + pub fn checkpoint_commit(&mut self) { + self.depth -= 1; + } + + /// Reverts all changes to state until given checkpoint. + #[inline] + pub fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) { + let is_spurious_dragon_enabled = SpecId::enabled(self.spec, SPURIOUS_DRAGON); + let state = &mut self.state; + let transient_storage = &mut self.transient_storage; + self.depth -= 1; + // iterate over last N journals sets and revert our global state + let leng = self.journal.len(); + self.journal + .iter_mut() + .rev() + .take(leng - checkpoint.journal_i) + .for_each(|cs| { + Self::journal_revert( + state, + transient_storage, + mem::take(cs), + is_spurious_dragon_enabled, + ) + }); + + self.logs.truncate(checkpoint.log_i); + self.journal.truncate(checkpoint.journal_i); + } + + /// Performances selfdestruct action. + /// Transfers balance from address to target. Check if target exist/is_cold + /// + /// Note: balance will be lost if address and target are the same BUT when + /// current spec enables Cancun, this happens only when the account associated to address + /// is created in the same tx + /// + /// references: + /// * + /// * + /// * + #[inline] + pub fn selfdestruct( + &mut self, + address: Address, + target: Address, + db: &mut DB, + ) -> Result> { + let load_result = self.load_account_exist(target, db)?; + + if address != target { + // Both accounts are loaded before this point, `address` as we execute its contract. + // and `target` at the beginning of the function. + let acc_balance = self.state.get_mut(&address).unwrap().info.balance; + + let target_account = self.state.get_mut(&target).unwrap(); + Self::touch_account(self.journal.last_mut().unwrap(), &target, target_account); + target_account.info.balance += acc_balance; + } + + let acc = self.state.get_mut(&address).unwrap(); + let balance = acc.info.balance; + let previously_destroyed = acc.is_selfdestructed(); + let is_cancun_enabled = SpecId::enabled(self.spec, CANCUN); + + // EIP-6780 (Cancun hard-fork): selfdestruct only if contract is created in the same tx + let journal_entry = if acc.is_created() || !is_cancun_enabled { + acc.mark_selfdestruct(); + acc.info.balance = U256::ZERO; + Some(JournalEntry::AccountDestroyed { + address, + target, + was_destroyed: previously_destroyed, + had_balance: balance, + }) + } else if address != target { + acc.info.balance = U256::ZERO; + Some(JournalEntry::BalanceTransfer { + from: address, + to: target, + balance, + }) + } else { + // State is not changed: + // * if we are after Cancun upgrade and + // * Selfdestruct account that is created in the same transaction and + // * Specify the target is same as selfdestructed account. The balance stays unchanged. + None + }; + + if let Some(entry) = journal_entry { + self.journal.last_mut().unwrap().push(entry); + }; + + Ok(SelfDestructResult { + had_value: balance != U256::ZERO, + is_cold: load_result.is_cold, + target_exists: !load_result.is_empty, + previously_destroyed, + }) + } + + /// Initial load of account. This load will not be tracked inside journal + #[inline] + pub fn initial_account_load( + &mut self, + address: Address, + slots: &[U256], + db: &mut DB, + ) -> Result<&mut Account, EVMError> { + // load or get account. + let account = match self.state.entry(address) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(vac) => vac.insert( + db.basic(address) + .map_err(EVMError::Database)? + .map(|i| i.into()) + .unwrap_or(Account::new_not_existing()), + ), + }; + // preload storages. + for slot in slots { + if let Entry::Vacant(entry) = account.storage.entry(*slot) { + let storage = db.storage(address, *slot).map_err(EVMError::Database)?; + entry.insert(StorageSlot::new(storage)); + } + } + Ok(account) + } + + /// load account into memory. return if it is cold or warm accessed + #[inline] + pub fn load_account( + &mut self, + address: Address, + db: &mut DB, + ) -> Result<(&mut Account, bool), EVMError> { + Ok(match self.state.entry(address) { + Entry::Occupied(entry) => (entry.into_mut(), false), + Entry::Vacant(vac) => { + let account = + if let Some(account) = db.basic(address).map_err(EVMError::Database)? { + account.into() + } else { + Account::new_not_existing() + }; + + // journal loading of account. AccessList touch. + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::AccountLoaded { address }); + + // precompiles are warm loaded so we need to take that into account + let is_cold = !self.warm_preloaded_addresses.contains(&address); + + (vac.insert(account), is_cold) + } + }) + } + + /// Load account from database to JournaledState. + /// + /// Return boolean pair where first is `is_cold` second bool `is_exists`. + #[inline] + pub fn load_account_exist( + &mut self, + address: Address, + db: &mut DB, + ) -> Result> { + let spec = self.spec; + let (acc, is_cold) = self.load_account(address, db)?; + + let is_spurious_dragon_enabled = SpecId::enabled(spec, SPURIOUS_DRAGON); + let is_empty = if is_spurious_dragon_enabled { + acc.is_empty() + } else { + let loaded_not_existing = acc.is_loaded_as_not_existing(); + let is_not_touched = !acc.is_touched(); + loaded_not_existing && is_not_touched + }; + + Ok(LoadAccountResult { is_empty, is_cold }) + } + + /// Loads code. + #[inline] + pub fn load_code( + &mut self, + address: Address, + db: &mut DB, + ) -> Result<(&mut Account, bool), EVMError> { + let (acc, is_cold) = self.load_account(address, db)?; + if acc.info.code.is_none() { + if acc.info.code_hash == KECCAK_EMPTY { + let empty = Bytecode::default(); + acc.info.code = Some(empty); + } else { + let code = db + .code_by_hash(acc.info.code_hash) + .map_err(EVMError::Database)?; + acc.info.code = Some(code); + } + } + Ok((acc, is_cold)) + } + + /// Load storage slot + /// + /// # Panics + /// + /// Panics if the account is not present in the state. + #[inline] + pub fn sload( + &mut self, + address: Address, + key: U256, + db: &mut DB, + ) -> Result<(U256, bool), EVMError> { + // assume acc is warm + let account = self.state.get_mut(&address).unwrap(); + // only if account is created in this tx we can assume that storage is empty. + let is_newly_created = account.is_created(); + let load = match account.storage.entry(key) { + Entry::Occupied(occ) => (occ.get().present_value, false), + Entry::Vacant(vac) => { + // if storage was cleared, we don't need to ping db. + let value = if is_newly_created { + U256::ZERO + } else { + db.storage(address, key).map_err(EVMError::Database)? + }; + // add it to journal as cold loaded. + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::StorageChange { + address, + key, + had_value: None, + }); + + vac.insert(StorageSlot::new(value)); + + (value, true) + } + }; + Ok(load) + } + + /// Stores storage slot. + /// And returns (original,present,new) slot value. + /// + /// Note: + /// + /// account should already be present in our state. + #[inline] + pub fn sstore( + &mut self, + address: Address, + key: U256, + new: U256, + db: &mut DB, + ) -> Result> { + // assume that acc exists and load the slot. + let (present, is_cold) = self.sload(address, key, db)?; + let acc = self.state.get_mut(&address).unwrap(); + + // if there is no original value in dirty return present value, that is our original. + let slot = acc.storage.get_mut(&key).unwrap(); + + // new value is same as present, we don't need to do anything + if present == new { + return Ok(SStoreResult { + original_value: slot.previous_or_original_value, + present_value: present, + new_value: new, + is_cold, + }); + } + + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::StorageChange { + address, + key, + had_value: Some(present), + }); + // insert value into present state. + slot.present_value = new; + Ok(SStoreResult { + original_value: slot.previous_or_original_value, + present_value: present, + new_value: new, + is_cold, + }) + } + + /// Read transient storage tied to the account. + /// + /// EIP-1153: Transient storage opcodes + #[inline] + pub fn tload(&mut self, address: Address, key: U256) -> U256 { + self.transient_storage + .get(&(address, key)) + .copied() + .unwrap_or_default() + } + + /// Store transient storage tied to the account. + /// + /// If values is different add entry to the journal + /// so that old state can be reverted if that action is needed. + /// + /// EIP-1153: Transient storage opcodes + #[inline] + pub fn tstore(&mut self, address: Address, key: U256, new: U256) { + let had_value = if new == U256::ZERO { + // if new values is zero, remove entry from transient storage. + // if previous values was some insert it inside journal. + // If it is none nothing should be inserted. + self.transient_storage.remove(&(address, key)) + } else { + // insert values + let previous_value = self + .transient_storage + .insert((address, key), new) + .unwrap_or_default(); + + // check if previous value is same + if previous_value != new { + // if it is different, insert previous values inside journal. + Some(previous_value) + } else { + None + } + }; + + if let Some(had_value) = had_value { + // insert in journal only if value was changed. + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::TransientStorageChange { + address, + key, + had_value, + }); + } + } + + /// push log into subroutine + #[inline] + pub fn log(&mut self, log: Log) { + self.logs.push(log); + } +} + +/// Journal entries that are used to track changes to the state and are used to revert it. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum JournalEntry { + /// Used to mark account that is warm inside EVM in regards to EIP-2929 AccessList. + /// Action: We will add Account to state. + /// Revert: we will remove account from state. + AccountLoaded { address: Address }, + /// Mark account to be destroyed and journal balance to be reverted + /// Action: Mark account and transfer the balance + /// Revert: Unmark the account and transfer balance back + AccountDestroyed { + address: Address, + target: Address, + was_destroyed: bool, // if account had already been destroyed before this journal entry + had_balance: U256, + }, + /// Loading account does not mean that account will need to be added to MerkleTree (touched). + /// Only when account is called (to execute contract or transfer balance) only then account is made touched. + /// Action: Mark account touched + /// Revert: Unmark account touched + AccountTouched { address: Address }, + /// Transfer balance between two accounts + /// Action: Transfer balance + /// Revert: Transfer balance back + BalanceTransfer { + from: Address, + to: Address, + balance: U256, + }, + /// Increment nonce + /// Action: Increment nonce by one + /// Revert: Decrement nonce by one + NonceChange { + address: Address, //geth has nonce value, + }, + /// Create account: + /// Actions: Mark account as created + /// Revert: Unmart account as created and reset nonce to zero. + AccountCreated { address: Address }, + /// It is used to track both storage change and warm load of storage slot. For warm load in regard + /// to EIP-2929 AccessList had_value will be None + /// Action: Storage change or warm load + /// Revert: Revert to previous value or remove slot from storage + StorageChange { + address: Address, + key: U256, + had_value: Option, //if none, storage slot was cold loaded from db and needs to be removed + }, + /// It is used to track an EIP-1153 transient storage change. + /// Action: Transient storage changed. + /// Revert: Revert to previous value. + TransientStorageChange { + address: Address, + key: U256, + had_value: U256, + }, + /// Code changed + /// Action: Account code changed + /// Revert: Revert to previous bytecode. + CodeChange { address: Address }, +} + +/// SubRoutine checkpoint that will help us to go back from this +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct JournalCheckpoint { + log_i: usize, + journal_i: usize, +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/lib.md b/docs/revm-python-spec/revm-verif/revm/revm/src/lib.md new file mode 100644 index 00000000..8eee6b4e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/lib.md @@ -0,0 +1,65 @@ +# ๐Ÿฆ€ lib.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/lib.rs) + +```rust +#![doc = "Revm is a Rust EVM implementation."] +#![warn(rustdoc::all, unreachable_pub)] +#![allow(rustdoc::bare_urls)] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +#![deny(unused_must_use, rust_2018_idioms)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[macro_use] +#[cfg(not(feature = "std"))] +extern crate alloc as std; + +// Define modules. + +mod builder; +mod context; + +#[cfg(any(test, feature = "test-utils"))] +pub mod test_utils; + +pub mod db; +mod evm; +mod frame; +pub mod handler; +mod inspector; +mod journaled_state; +#[cfg(feature = "optimism")] +pub mod optimism; + +// Export items. + +pub use builder::EvmBuilder; +pub use context::{ + Context, ContextPrecompile, ContextPrecompiles, ContextStatefulPrecompile, + ContextStatefulPrecompileArc, ContextStatefulPrecompileBox, ContextStatefulPrecompileMut, + ContextWithHandlerCfg, EvmContext, InnerEvmContext, +}; +pub use db::{ + CacheState, DBBox, State, StateBuilder, StateDBBox, TransitionAccount, TransitionState, +}; +pub use db::{Database, DatabaseCommit, DatabaseRef, InMemoryDB}; +pub use evm::{Evm, CALL_STACK_LIMIT}; +pub use frame::{CallFrame, CreateFrame, Frame, FrameData, FrameOrResult, FrameResult}; +pub use handler::Handler; +pub use inspector::{ + inspector_handle_register, inspector_instruction, inspectors, GetInspector, Inspector, +}; +pub use journaled_state::{JournalCheckpoint, JournalEntry, JournaledState}; +// export Optimism types, helpers, and constants +#[cfg(feature = "optimism")] +pub use optimism::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; + +// Reexport libraries + +#[doc(inline)] +pub use revm_interpreter as interpreter; +#[doc(inline)] +pub use revm_interpreter::primitives; +#[doc(inline)] +pub use revm_precompile as precompile; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/optimism.md b/docs/revm-python-spec/revm-verif/revm/revm/src/optimism.md new file mode 100644 index 00000000..6f12282f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/optimism.md @@ -0,0 +1,16 @@ +# ๐Ÿฆ€ optimism.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/optimism.rs) + +```rust +//! Optimism-specific constants, types, and helpers. + +mod handler_register; +mod l1block; + +pub use handler_register::{ + deduct_caller, end, last_frame_return, load_accounts, optimism_handle_register, output, + reward_beneficiary, validate_env, validate_tx_against_state, +}; +pub use l1block::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/optimism/handler_register.md b/docs/revm-python-spec/revm-verif/revm/revm/src/optimism/handler_register.md new file mode 100644 index 00000000..eef6eda9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/optimism/handler_register.md @@ -0,0 +1,638 @@ +# ๐Ÿฆ€ handler_register.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/optimism/handler_register.rs) + +```rust +//! Handler related to Optimism chain + +use crate::{ + handler::{ + mainnet::{self, deduct_caller_inner}, + register::EvmHandler, + }, + interpreter::{return_ok, return_revert, Gas, InstructionResult}, + optimism, + primitives::{ + db::Database, spec_to_generic, Account, EVMError, Env, ExecutionResult, HaltReason, + HashMap, InvalidTransaction, ResultAndState, Spec, SpecId, SpecId::REGOLITH, U256, + }, + Context, FrameResult, +}; +use core::ops::Mul; +use std::string::ToString; +use std::sync::Arc; + +pub fn optimism_handle_register(handler: &mut EvmHandler<'_, EXT, DB>) { + spec_to_generic!(handler.cfg.spec_id, { + // validate environment + handler.validation.env = Arc::new(validate_env::); + // Validate transaction against state. + handler.validation.tx_against_state = Arc::new(validate_tx_against_state::); + // load l1 data + handler.pre_execution.load_accounts = Arc::new(load_accounts::); + // An estimated batch cost is charged from the caller and added to L1 Fee Vault. + handler.pre_execution.deduct_caller = Arc::new(deduct_caller::); + // Refund is calculated differently then mainnet. + handler.execution.last_frame_return = Arc::new(last_frame_return::); + handler.post_execution.reward_beneficiary = Arc::new(reward_beneficiary::); + // In case of halt of deposit transaction return Error. + handler.post_execution.output = Arc::new(output::); + handler.post_execution.end = Arc::new(end::); + }); +} + +/// Validate environment for the Optimism chain. +pub fn validate_env(env: &Env) -> Result<(), EVMError> { + // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. + if env.tx.optimism.source_hash.is_some() { + return Ok(()); + } + // Important: validate block before tx. + env.validate_block_env::()?; + + // Do not allow for a system transaction to be processed if Regolith is enabled. + let tx = &env.tx.optimism; + if tx.is_system_transaction.unwrap_or(false) && SPEC::enabled(SpecId::REGOLITH) { + return Err(InvalidTransaction::DepositSystemTxPostRegolith.into()); + } + + env.validate_tx::()?; + Ok(()) +} + +/// Don not perform any extra validation for deposit transactions, they are pre-verified on L1. +pub fn validate_tx_against_state( + context: &mut Context, +) -> Result<(), EVMError> { + if context.evm.inner.env.tx.optimism.source_hash.is_some() { + return Ok(()); + } + mainnet::validate_tx_against_state::(context) +} + +/// Handle output of the transaction +#[inline] +pub fn last_frame_return( + context: &mut Context, + frame_result: &mut FrameResult, +) -> Result<(), EVMError> { + let env = context.evm.inner.env(); + let is_deposit = env.tx.optimism.source_hash.is_some(); + let tx_system = env.tx.optimism.is_system_transaction; + let tx_gas_limit = env.tx.gas_limit; + let is_regolith = SPEC::enabled(REGOLITH); + + let instruction_result = frame_result.interpreter_result().result; + let gas = frame_result.gas_mut(); + let remaining = gas.remaining(); + let refunded = gas.refunded(); + // Spend the gas limit. Gas is reimbursed when the tx returns successfully. + *gas = Gas::new_spent(tx_gas_limit); + + match instruction_result { + return_ok!() => { + // On Optimism, deposit transactions report gas usage uniquely to other + // transactions due to them being pre-paid on L1. + // + // Hardfork Behavior: + // - Bedrock (success path): + // - Deposit transactions (non-system) report their gas limit as the usage. + // No refunds. + // - Deposit transactions (system) report 0 gas used. No refunds. + // - Regular transactions report gas usage as normal. + // - Regolith (success path): + // - Deposit transactions (all) report their gas used as normal. Refunds + // enabled. + // - Regular transactions report their gas used as normal. + if !is_deposit || is_regolith { + // For regular transactions prior to Regolith and all transactions after + // Regolith, gas is reported as normal. + gas.erase_cost(remaining); + gas.record_refund(refunded); + } else if is_deposit && tx_system.unwrap_or(false) { + // System transactions were a special type of deposit transaction in + // the Bedrock hardfork that did not incur any gas costs. + gas.erase_cost(tx_gas_limit); + } + } + return_revert!() => { + // On Optimism, deposit transactions report gas usage uniquely to other + // transactions due to them being pre-paid on L1. + // + // Hardfork Behavior: + // - Bedrock (revert path): + // - Deposit transactions (all) report the gas limit as the amount of gas + // used on failure. No refunds. + // - Regular transactions receive a refund on remaining gas as normal. + // - Regolith (revert path): + // - Deposit transactions (all) report the actual gas used as the amount of + // gas used on failure. Refunds on remaining gas enabled. + // - Regular transactions receive a refund on remaining gas as normal. + if !is_deposit || is_regolith { + gas.erase_cost(remaining); + } + } + _ => {} + } + // Prior to Regolith, deposit transactions did not receive gas refunds. + let is_gas_refund_disabled = env.cfg.is_gas_refund_disabled() || (is_deposit && !is_regolith); + if !is_gas_refund_disabled { + gas.set_final_refund(SPEC::SPEC_ID.is_enabled_in(SpecId::LONDON)); + } + Ok(()) +} + +/// Load account (make them warm) and l1 data from database. +#[inline] +pub fn load_accounts( + context: &mut Context, +) -> Result<(), EVMError> { + // the L1-cost fee is only computed for Optimism non-deposit transactions. + + if context.evm.inner.env.tx.optimism.source_hash.is_none() { + let l1_block_info = + crate::optimism::L1BlockInfo::try_fetch(&mut context.evm.inner.db, SPEC::SPEC_ID) + .map_err(EVMError::Database)?; + + // storage l1 block info for later use. + context.evm.inner.l1_block_info = Some(l1_block_info); + } + + mainnet::load_accounts::(context) +} + +/// Deduct max balance from caller +#[inline] +pub fn deduct_caller( + context: &mut Context, +) -> Result<(), EVMError> { + // load caller's account. + let (caller_account, _) = context + .evm + .inner + .journaled_state + .load_account(context.evm.inner.env.tx.caller, &mut context.evm.inner.db)?; + + // If the transaction is a deposit with a `mint` value, add the mint value + // in wei to the caller's balance. This should be persisted to the database + // prior to the rest of execution. + if let Some(mint) = context.evm.inner.env.tx.optimism.mint { + caller_account.info.balance += U256::from(mint); + } + + // We deduct caller max balance after minting and before deducing the + // l1 cost, max values is already checked in pre_validate but l1 cost wasn't. + deduct_caller_inner::(caller_account, &context.evm.inner.env); + + // If the transaction is not a deposit transaction, subtract the L1 data fee from the + // caller's balance directly after minting the requested amount of ETH. + if context.evm.inner.env.tx.optimism.source_hash.is_none() { + // get envelope + let Some(enveloped_tx) = &context.evm.inner.env.tx.optimism.enveloped_tx else { + return Err(EVMError::Custom( + "[OPTIMISM] Failed to load enveloped transaction.".to_string(), + )); + }; + + let tx_l1_cost = context + .evm + .inner + .l1_block_info + .as_ref() + .expect("L1BlockInfo should be loaded") + .calculate_tx_l1_cost(enveloped_tx, SPEC::SPEC_ID); + if tx_l1_cost.gt(&caller_account.info.balance) { + return Err(EVMError::Transaction( + InvalidTransaction::LackOfFundForMaxFee { + fee: tx_l1_cost.into(), + balance: caller_account.info.balance.into(), + }, + )); + } + caller_account.info.balance = caller_account.info.balance.saturating_sub(tx_l1_cost); + } + Ok(()) +} + +/// Reward beneficiary with gas fee. +#[inline] +pub fn reward_beneficiary( + context: &mut Context, + gas: &Gas, +) -> Result<(), EVMError> { + let is_deposit = context.evm.inner.env.tx.optimism.source_hash.is_some(); + + // transfer fee to coinbase/beneficiary. + if !is_deposit { + mainnet::reward_beneficiary::(context, gas)?; + } + + if !is_deposit { + // If the transaction is not a deposit transaction, fees are paid out + // to both the Base Fee Vault as well as the L1 Fee Vault. + let Some(l1_block_info) = &context.evm.inner.l1_block_info else { + return Err(EVMError::Custom( + "[OPTIMISM] Failed to load L1 block information.".to_string(), + )); + }; + + let Some(enveloped_tx) = &context.evm.inner.env.tx.optimism.enveloped_tx else { + return Err(EVMError::Custom( + "[OPTIMISM] Failed to load enveloped transaction.".to_string(), + )); + }; + + let l1_cost = l1_block_info.calculate_tx_l1_cost(enveloped_tx, SPEC::SPEC_ID); + + // Send the L1 cost of the transaction to the L1 Fee Vault. + let Ok((l1_fee_vault_account, _)) = context + .evm + .inner + .journaled_state + .load_account(optimism::L1_FEE_RECIPIENT, &mut context.evm.inner.db) + else { + return Err(EVMError::Custom( + "[OPTIMISM] Failed to load L1 Fee Vault account.".to_string(), + )); + }; + l1_fee_vault_account.mark_touch(); + l1_fee_vault_account.info.balance += l1_cost; + + // Send the base fee of the transaction to the Base Fee Vault. + let Ok((base_fee_vault_account, _)) = context + .evm + .inner + .journaled_state + .load_account(optimism::BASE_FEE_RECIPIENT, &mut context.evm.inner.db) + else { + return Err(EVMError::Custom( + "[OPTIMISM] Failed to load Base Fee Vault account.".to_string(), + )); + }; + base_fee_vault_account.mark_touch(); + base_fee_vault_account.info.balance += context + .evm + .inner + .env + .block + .basefee + .mul(U256::from(gas.spent() - gas.refunded() as u64)); + } + Ok(()) +} + +/// Main return handle, returns the output of the transaction. +#[inline] +pub fn output( + context: &mut Context, + frame_result: FrameResult, +) -> Result> { + let result = mainnet::output::(context, frame_result)?; + + if result.result.is_halt() { + // Post-regolith, if the transaction is a deposit transaction and it halts, + // we bubble up to the global return handler. The mint value will be persisted + // and the caller nonce will be incremented there. + let is_deposit = context.evm.inner.env.tx.optimism.source_hash.is_some(); + if is_deposit && SPEC::enabled(REGOLITH) { + return Err(EVMError::Transaction( + InvalidTransaction::HaltedDepositPostRegolith, + )); + } + } + Ok(result) +} +/// Optimism end handle changes output if the transaction is a deposit transaction. +/// Deposit transaction can't be reverted and is always successful. +#[inline] +pub fn end( + context: &mut Context, + evm_output: Result>, +) -> Result> { + evm_output.or_else(|err| { + if matches!(err, EVMError::Transaction(_)) + && context.evm.inner.env().tx.optimism.source_hash.is_some() + { + // If the transaction is a deposit transaction and it failed + // for any reason, the caller nonce must be bumped, and the + // gas reported must be altered depending on the Hardfork. This is + // also returned as a special Halt variant so that consumers can more + // easily distinguish between a failed deposit and a failed + // normal transaction. + let caller = context.evm.inner.env().tx.caller; + + // Increment sender nonce and account balance for the mint amount. Deposits + // always persist the mint amount, even if the transaction fails. + let account = { + let mut acc = Account::from( + context + .evm + .db + .basic(caller) + .unwrap_or_default() + .unwrap_or_default(), + ); + acc.info.nonce = acc.info.nonce.saturating_add(1); + acc.info.balance = acc.info.balance.saturating_add(U256::from( + context.evm.inner.env().tx.optimism.mint.unwrap_or(0), + )); + acc.mark_touch(); + acc + }; + let state = HashMap::from([(caller, account)]); + + // The gas used of a failed deposit post-regolith is the gas + // limit of the transaction. pre-regolith, it is the gas limit + // of the transaction for non system transactions and 0 for system + // transactions. + let is_system_tx = context + .evm + .env() + .tx + .optimism + .is_system_transaction + .unwrap_or(false); + let gas_used = if SPEC::enabled(REGOLITH) || !is_system_tx { + context.evm.inner.env().tx.gas_limit + } else { + 0 + }; + + Ok(ResultAndState { + result: ExecutionResult::Halt { + reason: HaltReason::FailedDeposit, + gas_used, + }, + state, + }) + } else { + Err(err) + } + }) +} + +#[cfg(test)] +mod tests { + use revm_interpreter::{CallOutcome, InterpreterResult}; + + use super::*; + use crate::{ + db::{EmptyDB, InMemoryDB}, + primitives::{ + bytes, state::AccountInfo, Address, BedrockSpec, Bytes, Env, LatestSpec, RegolithSpec, + B256, + }, + L1BlockInfo, + }; + + /// Creates frame result. + fn call_last_frame_return( + env: Env, + instruction_result: InstructionResult, + gas: Gas, + ) -> Gas { + let mut ctx = Context::new_empty(); + ctx.evm.inner.env = Box::new(env); + let mut first_frame = FrameResult::Call(CallOutcome::new( + InterpreterResult { + result: instruction_result, + output: Bytes::new(), + gas, + }, + 0..0, + )); + last_frame_return::(&mut ctx, &mut first_frame).unwrap(); + *first_frame.gas() + } + + #[test] + fn test_revert_gas() { + let mut env = Env::default(); + env.tx.gas_limit = 100; + env.tx.optimism.source_hash = None; + + let gas = + call_last_frame_return::(env, InstructionResult::Revert, Gas::new(90)); + assert_eq!(gas.remaining(), 90); + assert_eq!(gas.spent(), 10); + assert_eq!(gas.refunded(), 0); + } + + #[test] + fn test_consume_gas() { + let mut env = Env::default(); + env.tx.gas_limit = 100; + env.tx.optimism.source_hash = Some(B256::ZERO); + + let gas = + call_last_frame_return::(env, InstructionResult::Stop, Gas::new(90)); + assert_eq!(gas.remaining(), 90); + assert_eq!(gas.spent(), 10); + assert_eq!(gas.refunded(), 0); + } + + #[test] + fn test_consume_gas_with_refund() { + let mut env = Env::default(); + env.tx.gas_limit = 100; + env.tx.optimism.source_hash = Some(B256::ZERO); + + let mut ret_gas = Gas::new(90); + ret_gas.record_refund(20); + + let gas = + call_last_frame_return::(env.clone(), InstructionResult::Stop, ret_gas); + assert_eq!(gas.remaining(), 90); + assert_eq!(gas.spent(), 10); + assert_eq!(gas.refunded(), 2); // min(20, 10/5) + + let gas = call_last_frame_return::(env, InstructionResult::Revert, ret_gas); + assert_eq!(gas.remaining(), 90); + assert_eq!(gas.spent(), 10); + assert_eq!(gas.refunded(), 0); + } + + #[test] + fn test_consume_gas_sys_deposit_tx() { + let mut env = Env::default(); + env.tx.gas_limit = 100; + env.tx.optimism.source_hash = Some(B256::ZERO); + + let gas = call_last_frame_return::(env, InstructionResult::Stop, Gas::new(90)); + assert_eq!(gas.remaining(), 0); + assert_eq!(gas.spent(), 100); + assert_eq!(gas.refunded(), 0); + } + + #[test] + fn test_commit_mint_value() { + let caller = Address::ZERO; + let mut db = InMemoryDB::default(); + db.insert_account_info( + caller, + AccountInfo { + balance: U256::from(1000), + ..Default::default() + }, + ); + let mut context: Context<(), InMemoryDB> = Context::new_with_db(db); + context.evm.inner.l1_block_info = Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..Default::default() + }); + // Enveloped needs to be some but it will deduce zero fee. + context.evm.inner.env.tx.optimism.enveloped_tx = Some(bytes!("")); + // added mint value is 10. + context.evm.inner.env.tx.optimism.mint = Some(10); + + deduct_caller::(&mut context).unwrap(); + + // Check the account balance is updated. + let (account, _) = context + .evm + .inner + .journaled_state + .load_account(caller, &mut context.evm.inner.db) + .unwrap(); + assert_eq!(account.info.balance, U256::from(1010)); + } + + #[test] + fn test_remove_l1_cost_non_deposit() { + let caller = Address::ZERO; + let mut db = InMemoryDB::default(); + db.insert_account_info( + caller, + AccountInfo { + balance: U256::from(1000), + ..Default::default() + }, + ); + let mut context: Context<(), InMemoryDB> = Context::new_with_db(db); + context.evm.inner.l1_block_info = Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..Default::default() + }); + // l1block cost is 1048 fee. + context.evm.inner.env.tx.optimism.enveloped_tx = Some(bytes!("FACADE")); + // added mint value is 10. + context.evm.inner.env.tx.optimism.mint = Some(10); + // Putting source_hash to some makes it a deposit transaction. + // so enveloped_tx gas cost is ignored. + context.evm.inner.env.tx.optimism.source_hash = Some(B256::ZERO); + + deduct_caller::(&mut context).unwrap(); + + // Check the account balance is updated. + let (account, _) = context + .evm + .inner + .journaled_state + .load_account(caller, &mut context.evm.inner.db) + .unwrap(); + assert_eq!(account.info.balance, U256::from(1010)); + } + + #[test] + fn test_remove_l1_cost() { + let caller = Address::ZERO; + let mut db = InMemoryDB::default(); + db.insert_account_info( + caller, + AccountInfo { + balance: U256::from(1049), + ..Default::default() + }, + ); + let mut context: Context<(), InMemoryDB> = Context::new_with_db(db); + context.evm.inner.l1_block_info = Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..Default::default() + }); + // l1block cost is 1048 fee. + context.evm.inner.env.tx.optimism.enveloped_tx = Some(bytes!("FACADE")); + deduct_caller::(&mut context).unwrap(); + + // Check the account balance is updated. + let (account, _) = context + .evm + .inner + .journaled_state + .load_account(caller, &mut context.evm.inner.db) + .unwrap(); + assert_eq!(account.info.balance, U256::from(1)); + } + + #[test] + fn test_remove_l1_cost_lack_of_funds() { + let caller = Address::ZERO; + let mut db = InMemoryDB::default(); + db.insert_account_info( + caller, + AccountInfo { + balance: U256::from(48), + ..Default::default() + }, + ); + let mut context: Context<(), InMemoryDB> = Context::new_with_db(db); + context.evm.inner.l1_block_info = Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..Default::default() + }); + // l1block cost is 1048 fee. + context.evm.inner.env.tx.optimism.enveloped_tx = Some(bytes!("FACADE")); + + assert_eq!( + deduct_caller::(&mut context), + Err(EVMError::Transaction( + InvalidTransaction::LackOfFundForMaxFee { + fee: Box::new(U256::from(1048)), + balance: Box::new(U256::from(48)), + }, + )) + ); + } + + #[test] + fn test_validate_sys_tx() { + // mark the tx as a system transaction. + let mut env = Env::default(); + env.tx.optimism.is_system_transaction = Some(true); + assert_eq!( + validate_env::(&env), + Err(EVMError::Transaction( + InvalidTransaction::DepositSystemTxPostRegolith + )) + ); + + // Pre-regolith system transactions should be allowed. + assert!(validate_env::(&env).is_ok()); + } + + #[test] + fn test_validate_deposit_tx() { + // Set source hash. + let mut env = Env::default(); + env.tx.optimism.source_hash = Some(B256::ZERO); + assert!(validate_env::(&env).is_ok()); + } + + #[test] + fn test_validate_tx_against_state_deposit_tx() { + // Set source hash. + let mut env = Env::default(); + env.tx.optimism.source_hash = Some(B256::ZERO); + + // Nonce and balance checks should be skipped for deposit transactions. + assert!(validate_env::(&env).is_ok()); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/optimism/l1block.md b/docs/revm-python-spec/revm-verif/revm/revm/src/optimism/l1block.md new file mode 100644 index 00000000..7a469302 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/optimism/l1block.md @@ -0,0 +1,319 @@ +# ๐Ÿฆ€ l1block.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/optimism/l1block.rs) + +```rust +use crate::primitives::{address, db::Database, Address, SpecId, U256}; +use core::ops::Mul; + +const ZERO_BYTE_COST: u64 = 4; +const NON_ZERO_BYTE_COST: u64 = 16; + +/// The two 4-byte Ecotone fee scalar values are packed into the same storage slot as the 8-byte sequence number. +/// Byte offset within the storage slot of the 4-byte baseFeeScalar attribute. +const BASE_FEE_SCALAR_OFFSET: usize = 16; +/// The two 4-byte Ecotone fee scalar values are packed into the same storage slot as the 8-byte sequence number. +/// Byte offset within the storage slot of the 4-byte blobBaseFeeScalar attribute. +const BLOB_BASE_FEE_SCALAR_OFFSET: usize = 20; + +const L1_BASE_FEE_SLOT: U256 = U256::from_limbs([1u64, 0, 0, 0]); +const L1_OVERHEAD_SLOT: U256 = U256::from_limbs([5u64, 0, 0, 0]); +const L1_SCALAR_SLOT: U256 = U256::from_limbs([6u64, 0, 0, 0]); + +/// [ECOTONE_L1_BLOB_BASE_FEE_SLOT] was added in the Ecotone upgrade and stores the L1 blobBaseFee attribute. +const ECOTONE_L1_BLOB_BASE_FEE_SLOT: U256 = U256::from_limbs([7u64, 0, 0, 0]); + +/// As of the ecotone upgrade, this storage slot stores the 32-bit basefeeScalar and blobBaseFeeScalar attributes at +/// offsets [BASE_FEE_SCALAR_OFFSET] and [BLOB_BASE_FEE_SCALAR_OFFSET] respectively. +const ECOTONE_L1_FEE_SCALARS_SLOT: U256 = U256::from_limbs([3u64, 0, 0, 0]); + +/// An empty 64-bit set of scalar values. +const EMPTY_SCALARS: [u8; 8] = [0u8; 8]; + +/// The address of L1 fee recipient. +pub const L1_FEE_RECIPIENT: Address = address!("420000000000000000000000000000000000001A"); + +/// The address of the base fee recipient. +pub const BASE_FEE_RECIPIENT: Address = address!("4200000000000000000000000000000000000019"); + +/// The address of the L1Block contract. +pub const L1_BLOCK_CONTRACT: Address = address!("4200000000000000000000000000000000000015"); + +/// L1 block info +/// +/// We can extract L1 epoch data from each L2 block, by looking at the `setL1BlockValues` +/// transaction data. This data is then used to calculate the L1 cost of a transaction. +/// +/// Here is the format of the `setL1BlockValues` transaction data: +/// +/// setL1BlockValues(uint64 _number, uint64 _timestamp, uint256 _basefee, bytes32 _hash, +/// uint64 _sequenceNumber, bytes32 _batcherHash, uint256 _l1FeeOverhead, uint256 _l1FeeScalar) +/// +/// For now, we only care about the fields necessary for L1 cost calculation. +#[derive(Clone, Debug, Default)] +pub struct L1BlockInfo { + /// The base fee of the L1 origin block. + pub l1_base_fee: U256, + /// The current L1 fee overhead. None if Ecotone is activated. + pub l1_fee_overhead: Option, + /// The current L1 fee scalar. + pub l1_base_fee_scalar: U256, + /// The current L1 blob base fee. None if Ecotone is not activated, except if `empty_scalars` is `true`. + pub l1_blob_base_fee: Option, + /// The current L1 blob base fee scalar. None if Ecotone is not activated. + pub l1_blob_base_fee_scalar: Option, + /// True if Ecotone is activated, but the L1 fee scalars have not yet been set. + pub(crate) empty_scalars: bool, +} + +impl L1BlockInfo { + /// Try to fetch the L1 block info from the database. + pub fn try_fetch(db: &mut DB, spec_id: SpecId) -> Result { + // Ensure the L1 Block account is loaded into the cache after Ecotone. With EIP-4788, it is no longer the case + // that the L1 block account is loaded into the cache prior to the first inquiry for the L1 block info. + if spec_id.is_enabled_in(SpecId::CANCUN) { + let _ = db.basic(L1_BLOCK_CONTRACT)?; + } + + let l1_base_fee = db.storage(L1_BLOCK_CONTRACT, L1_BASE_FEE_SLOT)?; + + if !spec_id.is_enabled_in(SpecId::ECOTONE) { + let l1_fee_overhead = db.storage(L1_BLOCK_CONTRACT, L1_OVERHEAD_SLOT)?; + let l1_fee_scalar = db.storage(L1_BLOCK_CONTRACT, L1_SCALAR_SLOT)?; + + Ok(L1BlockInfo { + l1_base_fee, + l1_fee_overhead: Some(l1_fee_overhead), + l1_base_fee_scalar: l1_fee_scalar, + ..Default::default() + }) + } else { + let l1_blob_base_fee = db.storage(L1_BLOCK_CONTRACT, ECOTONE_L1_BLOB_BASE_FEE_SLOT)?; + let l1_fee_scalars = db + .storage(L1_BLOCK_CONTRACT, ECOTONE_L1_FEE_SCALARS_SLOT)? + .to_be_bytes::<32>(); + + let l1_base_fee_scalar = U256::from_be_slice( + l1_fee_scalars[BASE_FEE_SCALAR_OFFSET..BASE_FEE_SCALAR_OFFSET + 4].as_ref(), + ); + let l1_blob_base_fee_scalar = U256::from_be_slice( + l1_fee_scalars[BLOB_BASE_FEE_SCALAR_OFFSET..BLOB_BASE_FEE_SCALAR_OFFSET + 4] + .as_ref(), + ); + + // Check if the L1 fee scalars are empty. If so, we use the Bedrock cost function. The L1 fee overhead is + // only necessary if `empty_scalars` is true, as it was deprecated in Ecotone. + let empty_scalars = l1_blob_base_fee == U256::ZERO + && l1_fee_scalars[BASE_FEE_SCALAR_OFFSET..BLOB_BASE_FEE_SCALAR_OFFSET + 4] + == EMPTY_SCALARS; + let l1_fee_overhead = empty_scalars + .then(|| db.storage(L1_BLOCK_CONTRACT, L1_OVERHEAD_SLOT)) + .transpose()?; + + Ok(L1BlockInfo { + l1_base_fee, + l1_base_fee_scalar, + l1_blob_base_fee: Some(l1_blob_base_fee), + l1_blob_base_fee_scalar: Some(l1_blob_base_fee_scalar), + empty_scalars, + l1_fee_overhead, + }) + } + } + + /// Calculate the data gas for posting the transaction on L1. Calldata costs 16 gas per non-zero + /// byte and 4 gas per zero byte. + /// + /// Prior to regolith, an extra 68 non-zero bytes were included in the rollup data costs to + /// account for the empty signature. + pub fn data_gas(&self, input: &[u8], spec_id: SpecId) -> U256 { + let mut rollup_data_gas_cost = U256::from(input.iter().fold(0, |acc, byte| { + acc + if *byte == 0x00 { + ZERO_BYTE_COST + } else { + NON_ZERO_BYTE_COST + } + })); + + // Prior to regolith, an extra 68 non zero bytes were included in the rollup data costs. + if !spec_id.is_enabled_in(SpecId::REGOLITH) { + rollup_data_gas_cost += U256::from(NON_ZERO_BYTE_COST).mul(U256::from(68)); + } + + rollup_data_gas_cost + } + + /// Calculate the gas cost of a transaction based on L1 block data posted on L2, depending on the [SpecId] passed. + pub fn calculate_tx_l1_cost(&self, input: &[u8], spec_id: SpecId) -> U256 { + // If the input is a deposit transaction or empty, the default value is zero. + if input.is_empty() || input.first() == Some(&0x7F) { + return U256::ZERO; + } + + if spec_id.is_enabled_in(SpecId::ECOTONE) { + self.calculate_tx_l1_cost_ecotone(input, spec_id) + } else { + self.calculate_tx_l1_cost_bedrock(input, spec_id) + } + } + + /// Calculate the gas cost of a transaction based on L1 block data posted on L2, pre-Ecotone. + fn calculate_tx_l1_cost_bedrock(&self, input: &[u8], spec_id: SpecId) -> U256 { + let rollup_data_gas_cost = self.data_gas(input, spec_id); + rollup_data_gas_cost + .saturating_add(self.l1_fee_overhead.unwrap_or_default()) + .saturating_mul(self.l1_base_fee) + .saturating_mul(self.l1_base_fee_scalar) + .wrapping_div(U256::from(1_000_000)) + } + + /// Calculate the gas cost of a transaction based on L1 block data posted on L2, post-Ecotone. + /// + /// [SpecId::ECOTONE] L1 cost function: + /// `(calldataGas/16)*(l1BaseFee*16*l1BaseFeeScalar + l1BlobBaseFee*l1BlobBaseFeeScalar)/1e6` + /// + /// We divide "calldataGas" by 16 to change from units of calldata gas to "estimated # of bytes when compressed". + /// Known as "compressedTxSize" in the spec. + /// + /// Function is actually computed as follows for better precision under integer arithmetic: + /// `calldataGas*(l1BaseFee*16*l1BaseFeeScalar + l1BlobBaseFee*l1BlobBaseFeeScalar)/16e6` + fn calculate_tx_l1_cost_ecotone(&self, input: &[u8], spec_id: SpecId) -> U256 { + // There is an edgecase where, for the very first Ecotone block (unless it is activated at Genesis), we must + // use the Bedrock cost function. To determine if this is the case, we can check if the Ecotone parameters are + // unset. + if self.empty_scalars { + return self.calculate_tx_l1_cost_bedrock(input, spec_id); + } + + let rollup_data_gas_cost = self.data_gas(input, spec_id); + let calldata_cost_per_byte = self + .l1_base_fee + .saturating_mul(U256::from(16)) + .saturating_mul(self.l1_base_fee_scalar); + let blob_cost_per_byte = self + .l1_blob_base_fee + .unwrap_or_default() + .saturating_mul(self.l1_blob_base_fee_scalar.unwrap_or_default()); + + calldata_cost_per_byte + .saturating_add(blob_cost_per_byte) + .saturating_mul(rollup_data_gas_cost) + .wrapping_div(U256::from(1_000_000 * 16)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::primitives::bytes; + + #[test] + fn test_data_gas_non_zero_bytes() { + let l1_block_info = L1BlockInfo { + l1_base_fee: U256::from(1_000_000), + l1_fee_overhead: Some(U256::from(1_000_000)), + l1_base_fee_scalar: U256::from(1_000_000), + ..Default::default() + }; + + // 0xFACADE = 6 nibbles = 3 bytes + // 0xFACADE = 1111 1010 . 1100 1010 . 1101 1110 + + // Pre-regolith (ie bedrock) has an extra 68 non-zero bytes + // gas cost = 3 non-zero bytes * NON_ZERO_BYTE_COST + NON_ZERO_BYTE_COST * 68 + // gas cost = 3 * 16 + 68 * 16 = 1136 + let input = bytes!("FACADE"); + let bedrock_data_gas = l1_block_info.data_gas(&input, SpecId::BEDROCK); + assert_eq!(bedrock_data_gas, U256::from(1136)); + + // Regolith has no added 68 non zero bytes + // gas cost = 3 * 16 = 48 + let regolith_data_gas = l1_block_info.data_gas(&input, SpecId::REGOLITH); + assert_eq!(regolith_data_gas, U256::from(48)); + } + + #[test] + fn test_data_gas_zero_bytes() { + let l1_block_info = L1BlockInfo { + l1_base_fee: U256::from(1_000_000), + l1_fee_overhead: Some(U256::from(1_000_000)), + l1_base_fee_scalar: U256::from(1_000_000), + ..Default::default() + }; + + // 0xFA00CA00DE = 10 nibbles = 5 bytes + // 0xFA00CA00DE = 1111 1010 . 0000 0000 . 1100 1010 . 0000 0000 . 1101 1110 + + // Pre-regolith (ie bedrock) has an extra 68 non-zero bytes + // gas cost = 3 non-zero * NON_ZERO_BYTE_COST + 2 * ZERO_BYTE_COST + NON_ZERO_BYTE_COST * 68 + // gas cost = 3 * 16 + 2 * 4 + 68 * 16 = 1144 + let input = bytes!("FA00CA00DE"); + let bedrock_data_gas = l1_block_info.data_gas(&input, SpecId::BEDROCK); + assert_eq!(bedrock_data_gas, U256::from(1144)); + + // Regolith has no added 68 non zero bytes + // gas cost = 3 * 16 + 2 * 4 = 56 + let regolith_data_gas = l1_block_info.data_gas(&input, SpecId::REGOLITH); + assert_eq!(regolith_data_gas, U256::from(56)); + } + + #[test] + fn test_calculate_tx_l1_cost() { + let l1_block_info = L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..Default::default() + }; + + let input = bytes!("FACADE"); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::REGOLITH); + assert_eq!(gas_cost, U256::from(1048)); + + // Zero rollup data gas cost should result in zero + let input = bytes!(""); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::REGOLITH); + assert_eq!(gas_cost, U256::ZERO); + + // Deposit transactions with the EIP-2718 type of 0x7F should result in zero + let input = bytes!("7FFACADE"); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::REGOLITH); + assert_eq!(gas_cost, U256::ZERO); + } + + #[test] + fn test_calculate_tx_l1_cost_ecotone() { + let mut l1_block_info = L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_base_fee_scalar: U256::from(1_000), + l1_blob_base_fee: Some(U256::from(1_000)), + l1_blob_base_fee_scalar: Some(U256::from(1_000)), + l1_fee_overhead: Some(U256::from(1_000)), + ..Default::default() + }; + + // calldataGas * (l1BaseFee * 16 * l1BaseFeeScalar + l1BlobBaseFee * l1BlobBaseFeeScalar) / (16 * 1e6) + // = (16 * 3) * (1000 * 16 * 1000 + 1000 * 1000) / (16 * 1e6) + // = 51 + let input = bytes!("FACADE"); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::ECOTONE); + assert_eq!(gas_cost, U256::from(51)); + + // Zero rollup data gas cost should result in zero + let input = bytes!(""); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::ECOTONE); + assert_eq!(gas_cost, U256::ZERO); + + // Deposit transactions with the EIP-2718 type of 0x7F should result in zero + let input = bytes!("7FFACADE"); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::ECOTONE); + assert_eq!(gas_cost, U256::ZERO); + + // If the scalars are empty, the bedrock cost function should be used. + l1_block_info.empty_scalars = true; + let input = bytes!("FACADE"); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::ECOTONE); + assert_eq!(gas_cost, U256::from(1048)); + } +} +``` diff --git a/docs/revm-python-spec/revm-verif/revm/revm/src/test_utils.md b/docs/revm-python-spec/revm-verif/revm/revm/src/test_utils.md new file mode 100644 index 00000000..5a7b3b98 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/revm/revm/src/test_utils.md @@ -0,0 +1,8 @@ +# ๐Ÿฆ€ test_utils.rs + +[๐Ÿ™ GitHub source](https://github.com/bluealloy/revm/tree/99e177d6bedf3823a717d3017b3cfeb98ed2aeac/crates/revm/src/test_utils.rs) + +```rust +#[doc(hidden)] +pub use crate::context::evm_context::test_utils::*; +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/__init__.md new file mode 100644 index 00000000..0972689d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/__init__.md @@ -0,0 +1,64 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/./__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +### 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. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Definition __version__ : Value.t := M.run ltac:(M.monadic ( + Constant.str "0.1.0" +)). + +Definition EVM_RECURSION_LIMIT : Value.t := M.run ltac:(M.monadic ( + BinOp.mult (| + Constant.int 1024, + Constant.int 12 + |) +)). + +Definition expr_27 : Value.t := + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "sys" |), "setrecursionlimit" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "EVM_RECURSION_LIMIT" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "sys" |), "getrecursionlimit" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/__init__.md new file mode 100644 index 00000000..5558eeda --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/__init__.md @@ -0,0 +1,30 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +The Arrow Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 13773000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/blocks.md new file mode 100644 index 00000000..b6561fdb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/blocks.md @@ -0,0 +1,93 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.arrow_glacier.fork_types" "Bloom". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". + +Axiom ethereum_arrow_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "LegacyTransaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/bloom.md new file mode 100644 index 00000000..97566361 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". + +Axiom ethereum_arrow_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.arrow_glacier.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/fork.md new file mode 100644 index 00000000..e1c4ca15 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/fork.md @@ -0,0 +1,3592 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_imports_vm : + IsImported globals "ethereum.arrow_glacier" "vm". + +Axiom ethereum_arrow_glacier_blocks_imports_Block : + IsImported globals "ethereum.arrow_glacier.blocks" "Block". +Axiom ethereum_arrow_glacier_blocks_imports_Header : + IsImported globals "ethereum.arrow_glacier.blocks" "Header". +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". +Axiom ethereum_arrow_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.arrow_glacier.blocks" "Receipt". + +Axiom ethereum_arrow_glacier_bloom_imports_logs_bloom : + IsImported globals "ethereum.arrow_glacier.bloom" "logs_bloom". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.arrow_glacier.fork_types" "Bloom". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". + +Axiom ethereum_arrow_glacier_state_imports_State : + IsImported globals "ethereum.arrow_glacier.state" "State". +Axiom ethereum_arrow_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.arrow_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_arrow_glacier_state_imports_create_ether : + IsImported globals "ethereum.arrow_glacier.state" "create_ether". +Axiom ethereum_arrow_glacier_state_imports_destroy_account : + IsImported globals "ethereum.arrow_glacier.state" "destroy_account". +Axiom ethereum_arrow_glacier_state_imports_get_account : + IsImported globals "ethereum.arrow_glacier.state" "get_account". +Axiom ethereum_arrow_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.arrow_glacier.state" "increment_nonce". +Axiom ethereum_arrow_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.arrow_glacier.state" "set_account_balance". +Axiom ethereum_arrow_glacier_state_imports_state_root : + IsImported globals "ethereum.arrow_glacier.state" "state_root". + +Axiom ethereum_arrow_glacier_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_arrow_glacier_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_arrow_glacier_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_BASE_COST". +Axiom ethereum_arrow_glacier_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_CREATE_COST". +Axiom ethereum_arrow_glacier_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_arrow_glacier_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_arrow_glacier_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "AccessListTransaction". +Axiom ethereum_arrow_glacier_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "FeeMarketTransaction". +Axiom ethereum_arrow_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "LegacyTransaction". +Axiom ethereum_arrow_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.arrow_glacier.transactions" "Transaction". +Axiom ethereum_arrow_glacier_transactions_imports_decode_transaction : + IsImported globals "ethereum.arrow_glacier.transactions" "decode_transaction". +Axiom ethereum_arrow_glacier_transactions_imports_encode_transaction : + IsImported globals "ethereum.arrow_glacier.transactions" "encode_transaction". + +Axiom ethereum_arrow_glacier_trie_imports_Trie : + IsImported globals "ethereum.arrow_glacier.trie" "Trie". +Axiom ethereum_arrow_glacier_trie_imports_root : + IsImported globals "ethereum.arrow_glacier.trie" "root". +Axiom ethereum_arrow_glacier_trie_imports_trie_set : + IsImported globals "ethereum.arrow_glacier.trie" "trie_set". + +Axiom ethereum_arrow_glacier_utils_message_imports_prepare_message : + IsImported globals "ethereum.arrow_glacier.utils.message" "prepare_message". + +Axiom ethereum_arrow_glacier_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.arrow_glacier.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 10700000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_limit" |); + M.get_name (| globals, locals_stack, "parent_gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_target" |), + M.get_name (| globals, locals_stack, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_base_fee_per_gas_in_globals : + IsInGlobals globals "calculate_base_fee_per_gas" (make_function calculate_base_fee_per_gas). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |); + M.get_name (| globals, locals_stack, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "base_fee_per_gas" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "map" |), + make_list [ + M.get_name (| globals, locals_stack, "decode_transaction" |); + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "encode_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "base_fee_per_gas" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "_address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |), + M.get_name (| globals, locals_stack, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_2930_in_globals : + IsInGlobals globals "signing_hash_2930" (make_function signing_hash_2930). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_1559_in_globals : + IsInGlobals globals "signing_hash_1559" (make_function signing_hash_1559). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/fork_types.md new file mode 100644 index 00000000..698e4c1d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/state.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/state.md new file mode 100644 index 00000000..c46e7fea --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/state.md @@ -0,0 +1,1391 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_arrow_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.arrow_glacier.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_arrow_glacier_fork_types_imports_Account : + IsImported globals "ethereum.arrow_glacier.fork_types" "Account". +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". + +Axiom ethereum_arrow_glacier_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.arrow_glacier.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_arrow_glacier_trie_imports_Trie : + IsImported globals "ethereum.arrow_glacier.trie" "Trie". +Axiom ethereum_arrow_glacier_trie_imports_copy_trie : + IsImported globals "ethereum.arrow_glacier.trie" "copy_trie". +Axiom ethereum_arrow_glacier_trie_imports_root : + IsImported globals "ethereum.arrow_glacier.trie" "root". +Axiom ethereum_arrow_glacier_trie_imports_trie_get : + IsImported globals "ethereum.arrow_glacier.trie" "trie_get". +Axiom ethereum_arrow_glacier_trie_imports_trie_set : + IsImported globals "ethereum.arrow_glacier.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom mark_account_created_in_globals : + IsInGlobals globals "mark_account_created" (make_function mark_account_created). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "_" |); M.get_name (| globals, locals_stack, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "original_account_trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "original_value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "original_value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_original_in_globals : + IsInGlobals globals "get_storage_original" (make_function get_storage_original). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/transactions.md new file mode 100644 index 00000000..de15fecc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/transactions.md @@ -0,0 +1,306 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AccessListTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition FeeMarketTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_transaction_in_globals : + IsInGlobals globals "encode_transaction" (make_function encode_transaction). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom decode_transaction_in_globals : + IsInGlobals globals "decode_transaction" (make_function decode_transaction). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/trie.md new file mode 100644 index 00000000..514762a8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/trie.md @@ -0,0 +1,1645 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_london_imports_trie : + IsImported globals "ethereum.london" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_arrow_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.arrow_glacier.blocks" "Receipt". + +Axiom ethereum_arrow_glacier_fork_types_imports_Account : + IsImported globals "ethereum.arrow_glacier.fork_types" "Account". +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". +Axiom ethereum_arrow_glacier_fork_types_imports_encode_account : + IsImported globals "ethereum.arrow_glacier.fork_types" "encode_account". + +Axiom ethereum_arrow_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/__init__.md new file mode 100644 index 00000000..7146ff9e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/address.md new file mode 100644 index 00000000..89e0cb7c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this arrow_glacier version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/hexadecimal.md new file mode 100644 index 00000000..13355109 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.arrow_glacier.fork_types" "Bloom". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/message.md new file mode 100644 index 00000000..79b08996 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/utils/message.md @@ -0,0 +1,278 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_state_imports_get_account : + IsImported globals "ethereum.arrow_glacier.state" "get_account". + +Axiom ethereum_arrow_glacier_vm_imports_Environment : + IsImported globals "ethereum.arrow_glacier.vm" "Environment". +Axiom ethereum_arrow_glacier_vm_imports_Message : + IsImported globals "ethereum.arrow_glacier.vm" "Message". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_arrow_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, locals_stack, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/__init__.md new file mode 100644 index 00000000..7d944353 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/__init__.md @@ -0,0 +1,273 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_state_imports_State : + IsImported globals "ethereum.arrow_glacier.state" "State". +Axiom ethereum_arrow_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.arrow_glacier.state" "account_exists_and_is_empty". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/exceptions.md new file mode 100644 index 00000000..aedb69e4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/exceptions.md @@ -0,0 +1,181 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidParameter : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidContractPrefix : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/gas.md new file mode 100644 index 00000000..870cc9f7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/gas.md @@ -0,0 +1,938 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/__init__.md new file mode 100644 index 00000000..19b0d0ae --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "arithmetic". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_bitwise : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "bitwise". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_block : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "block". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_comparison : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "comparison". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_control_flow : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "control_flow". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_environment : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "environment". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_keccak : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "keccak". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_log : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "log". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_memory : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "memory". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_stack : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "stack". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_storage : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "storage". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_system : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/arithmetic.md new file mode 100644 index 00000000..a1ce3780 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_MID". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/bitwise.md new file mode 100644 index 00000000..a8bb5427 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/block.md new file mode 100644 index 00000000..6219eb97 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/block.md @@ -0,0 +1,426 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom chain_id_in_globals : + IsInGlobals globals "chain_id" (make_function chain_id). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/comparison.md new file mode 100644 index 00000000..d24bcfde --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/control_flow.md new file mode 100644 index 00000000..ba78256f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_HIGH". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_MID". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/environment.md new file mode 100644 index 00000000..8af95697 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/environment.md @@ -0,0 +1,1610 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.arrow_glacier.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_arrow_glacier_state_imports_get_account : + IsImported globals "ethereum.arrow_glacier.state" "get_account". + +Axiom ethereum_arrow_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "to_address". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_write". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_COPY". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom self_balance_in_globals : + IsInGlobals globals "self_balance" (make_function self_balance). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom base_fee_in_globals : + IsInGlobals globals "base_fee" (make_function base_fee). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/keccak.md new file mode 100644 index 00000000..7d4e4c6a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_KECCAK256". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/log.md new file mode 100644 index 00000000..f8e719ce --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_LOG". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/memory.md new file mode 100644 index 00000000..672f2ea1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_write". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/stack.md new file mode 100644 index 00000000..b0cfa746 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". +Axiom ethereum_arrow_glacier_vm_imports_stack : + IsImported globals "ethereum.arrow_glacier.vm" "stack". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/storage.md new file mode 100644 index 00000000..36f86e7b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/storage.md @@ -0,0 +1,512 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_state_imports_get_storage : + IsImported globals "ethereum.arrow_glacier.state" "get_storage". +Axiom ethereum_arrow_glacier_state_imports_get_storage_original : + IsImported globals "ethereum.arrow_glacier.state" "get_storage_original". +Axiom ethereum_arrow_glacier_state_imports_set_storage : + IsImported globals "ethereum.arrow_glacier.state" "set_storage". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/system.md new file mode 100644 index 00000000..01d4a4f9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/instructions/system.md @@ -0,0 +1,2276 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.arrow_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_arrow_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.arrow_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_arrow_glacier_state_imports_get_account : + IsImported globals "ethereum.arrow_glacier.state" "get_account". +Axiom ethereum_arrow_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.arrow_glacier.state" "increment_nonce". +Axiom ethereum_arrow_glacier_state_imports_is_account_alive : + IsImported globals "ethereum.arrow_glacier.state" "is_account_alive". +Axiom ethereum_arrow_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.arrow_glacier.state" "set_account_balance". + +Axiom ethereum_arrow_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "compute_contract_address". +Axiom ethereum_arrow_glacier_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "compute_create2_contract_address". +Axiom ethereum_arrow_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "to_address". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". +Axiom ethereum_arrow_glacier_vm_imports_Message : + IsImported globals "ethereum.arrow_glacier.vm" "Message". +Axiom ethereum_arrow_glacier_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.arrow_glacier.vm" "incorporate_child_on_error". +Axiom ethereum_arrow_glacier_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.arrow_glacier.vm" "incorporate_child_on_success". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "Revert". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_CREATE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_ZERO". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_message_call_gas". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". +Axiom ethereum_arrow_glacier_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "max_message_call_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_write". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "beneficiary" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/interpreter.md new file mode 100644 index 00000000..b7daf3e2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/interpreter.md @@ -0,0 +1,695 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.arrow_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_arrow_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.arrow_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_arrow_glacier_state_imports_begin_transaction : + IsImported globals "ethereum.arrow_glacier.state" "begin_transaction". +Axiom ethereum_arrow_glacier_state_imports_commit_transaction : + IsImported globals "ethereum.arrow_glacier.state" "commit_transaction". +Axiom ethereum_arrow_glacier_state_imports_destroy_storage : + IsImported globals "ethereum.arrow_glacier.state" "destroy_storage". +Axiom ethereum_arrow_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.arrow_glacier.state" "increment_nonce". +Axiom ethereum_arrow_glacier_state_imports_mark_account_created : + IsImported globals "ethereum.arrow_glacier.state" "mark_account_created". +Axiom ethereum_arrow_glacier_state_imports_move_ether : + IsImported globals "ethereum.arrow_glacier.state" "move_ether". +Axiom ethereum_arrow_glacier_state_imports_rollback_transaction : + IsImported globals "ethereum.arrow_glacier.state" "rollback_transaction". +Axiom ethereum_arrow_glacier_state_imports_set_code : + IsImported globals "ethereum.arrow_glacier.state" "set_code". +Axiom ethereum_arrow_glacier_state_imports_touch_account : + IsImported globals "ethereum.arrow_glacier.state" "touch_account". + +Axiom ethereum_arrow_glacier_vm_imports_Message : + IsImported globals "ethereum.arrow_glacier.vm" "Message". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_arrow_glacier_vm_imports_Environment : + IsImported globals "ethereum.arrow_glacier.vm" "Environment". +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "AddressCollision". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "InvalidOpcode". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "Revert". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "Ops". +Axiom ethereum_arrow_glacier_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "op_implementation". + +Axiom ethereum_arrow_glacier_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.arrow_glacier.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/memory.md new file mode 100644 index 00000000..96aa4eb8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..0c806545 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/__init__.md @@ -0,0 +1,124 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_arrow_glacier_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.arrow_glacier.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..e455187a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..8e1a8166 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,144 @@ +# ๐Ÿ“ blake2f.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.precompiled_contracts.blake2f". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, locals_stack, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, locals_stack, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, locals_stack, "rounds" |); + M.get_name (| globals, locals_stack, "h" |); + M.get_name (| globals, locals_stack, "m" |); + M.get_name (| globals, locals_stack, "t_0" |); + M.get_name (| globals, locals_stack, "t_1" |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom blake2f_in_globals : + IsInGlobals globals "blake2f" (make_function blake2f). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..6046ebfb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..dff84ea2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_IDENTITY". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..d3cb4201 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/mapping.md @@ -0,0 +1,80 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..a261689f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/modexp.md @@ -0,0 +1,700 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |); + M.get_name (| globals, locals_stack, "exp_length" |); + M.get_name (| globals, locals_stack, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Axiom complexity_in_globals : + IsInGlobals globals "complexity" (make_function complexity). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, locals_stack, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, locals_stack, "length_part" |), + M.get_name (| globals, locals_stack, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "count" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom iterations_in_globals : + IsInGlobals globals "iterations" (make_function iterations). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, locals_stack, "complexity" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, locals_stack, "iterations" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |); + M.get_name (| globals, locals_stack, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "multiplication_complexity" |), + M.get_name (| globals, locals_stack, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom gas_cost_in_globals : + IsInGlobals globals "gas_cost" (make_function gas_cost). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..79bbd304 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..783a4896 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_SHA256". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/runtime.md new file mode 100644 index 00000000..a8cc8678 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/stack.md new file mode 100644 index 00000000..977019f7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/arrow_glacier/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/arrow_glacier/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.arrow_glacier.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "StackOverflowError". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/base_types.md b/docs/revm-python-spec/revm-verif/spec-coq/base_types.md new file mode 100644 index 00000000..aa185d85 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/base_types.md @@ -0,0 +1,4517 @@ +# ๐Ÿ“ base_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/./base_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.base_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Integer and array types which are used byโ€”but not unique toโ€”Ethereum. + +[`Uint`] represents non-negative integers of arbitrary size, while subclasses +of [`FixedUint`] (like [`U256`] or [`U32`]) represent non-negative integers of +particular sizes. + +Similarly, [`Bytes`] represents arbitrarily long byte sequences, while +subclasses of [`FixedBytes`] (like [`Bytes0`] or [`Bytes64`]) represent +sequences containing an exact number of bytes. + +[`Uint`]: ref:ethereum.base_types.Uint +[`FixedUint`]: ref:ethereum.base_types.FixedUint +[`U32`]: ref:ethereum.base_types.U32 +[`U256`]: ref:ethereum.base_types.U256 +[`Bytes`]: ref:ethereum.base_types.Bytes +[`FixedBytes`]: ref:ethereum.base_types.FixedBytes +[`Bytes0`]: ref:ethereum.base_types.Bytes0 +[`Bytes64`]: ref:ethereum.base_types.Bytes64 +". + +Axiom dataclasses_imports_is_dataclass : + IsImported globals "dataclasses" "is_dataclass". +Axiom dataclasses_imports_replace : + IsImported globals "dataclasses" "replace". + +Axiom typing_imports_Any : + IsImported globals "typing" "Any". +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_ClassVar : + IsImported globals "typing" "ClassVar". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Protocol : + IsImported globals "typing" "Protocol". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_runtime_checkable : + IsImported globals "typing" "runtime_checkable". + +Definition SlottedFreezable : Value.t := make_klass {| + Klass.bases := [ + (globals, "Protocol") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition U255_CEIL_VALUE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 255 + |) +)). + +Definition expr_50 : Value.t := + Constant.str " +Smallest value that requires 256 bits to represent. Mostly used in signed +arithmetic operations, like [`sdiv`]. + +[`sdiv`]: ref:ethereum.frontier.vm.instructions.arithmetic.sdiv +". + +Definition U256_CEIL_VALUE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 256 + |) +)). + +Definition expr_58 : Value.t := + Constant.str " +Smallest value that requires 257 bits to represent. Used when converting a +[`U256`] in two's complement format to a regular `int` in [`U256.to_signed`]. + +[`U256`]: ref:ethereum.base_types.U256 +[`U256.to_signed`]: ref:ethereum.base_types.U256.to_signed +". + +Definition Uint : Value.t := make_klass {| + Klass.bases := [ + (globals, "int") + ]; + Klass.class_methods := [ + ( + "from_be_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "buffer" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts a sequence of bytes into an arbitrarily sized unsigned integer + from its big endian representation. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "from_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |); + Constant.str "big" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "from_le_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "buffer" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts a sequence of bytes into an arbitrarily sized unsigned integer + from its little endian representation. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "from_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |); + Constant.str "little" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "value" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "TypeError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)) + ); + ( + "__radd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__iadd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__sub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, locals_stack, "self" |), + M.get_name (| globals, locals_stack, "right" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__sub__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rsub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "self" |), + M.get_name (| globals, locals_stack, "left" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rsub__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__isub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__sub__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__mul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rmul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__imul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__floordiv__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__floordiv__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rfloordiv__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rfloordiv__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__ifloordiv__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__floordiv__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__mod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__mod__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rmod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rmod__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__imod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mod__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__divmod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__divmod__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + make_tuple [ M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "result" |), + Constant.int 0 + |) + ], + make_dict [] + |); M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "result" |), + Constant.int 1 + |) + ], + make_dict [] + |) ] + |) in + M.pure Constant.None_)) + ); + ( + "__rdivmod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rdivmod__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + make_tuple [ M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "result" |), + Constant.int 0 + |) + ], + make_dict [] + |); M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "result" |), + Constant.int 1 + |) + ], + make_dict [] + |) ] + |) in + M.pure Constant.None_)) + ); + ( + "__pow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right"; "modulo" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "modulo" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__pow__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "modulo" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rpow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left"; "modulo" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "modulo" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rpow__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "modulo" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__ipow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right"; "modulo" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__pow__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "modulo" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__xor__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__xor__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rxor__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rxor__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__ixor__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__xor__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "to_be_bytes32", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this arbitrarily sized unsigned integer into its big endian + representation with exactly 32 bytes. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes32" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + Constant.int 32; + Constant.str "big" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "to_be_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this arbitrarily sized unsigned integer into its big endian + representation, without padding. + " in + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "byte_length" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "to_le_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "number_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this arbitrarily sized unsigned integer into its little endian + representation, without padding. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "number_bytes" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "number_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "number_bytes" |); + Constant.str "little" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition T : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "T" + ], + make_dict [] + |) +)). + +Definition FixedUint : Value.t := make_klass {| + Klass.bases := [ + (globals, "int") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "value" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "TypeError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)) + ); + ( + "__radd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "result" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "wrapping_add", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Return a new instance containing `self + right (mod N)`. + + Passing a `right` value greater than [`MAX_VALUE`] or less than zero + will raise a `ValueError`, even if the result would fit in this integer + type. + + [`MAX_VALUE`]: ref:ethereum.base_types.FixedUint.MAX_VALUE + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__iadd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__sub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, locals_stack, "self" |), + M.get_name (| globals, locals_stack, "right" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__sub__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "wrapping_sub", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Return a new instance containing `self - right (mod N)`. + + Passing a `right` value greater than [`MAX_VALUE`] or less than zero + will raise a `ValueError`, even if the result would fit in this integer + type. + + [`MAX_VALUE`]: ref:ethereum.base_types.FixedUint.MAX_VALUE + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__sub__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rsub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "self" |), + M.get_name (| globals, locals_stack, "left" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rsub__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__isub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__sub__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__mul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "result" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "wrapping_mul", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Return a new instance containing `self * right (mod N)`. + + Passing a `right` value greater than [`MAX_VALUE`] or less than zero + will raise a `ValueError`, even if the result would fit in this integer + type. + + [`MAX_VALUE`]: ref:ethereum.base_types.FixedUint.MAX_VALUE + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rmul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__imul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__floordiv__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__floordiv__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rfloordiv__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rfloordiv__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__ifloordiv__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__floordiv__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__mod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__mod__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rmod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rmod__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__imod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mod__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__divmod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [ + M.get_name (| globals, locals_stack, "FixedUint" |); + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |), "__divmod__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + make_tuple [ M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "result" |), + Constant.int 0 + |) + ], + make_dict [] + |); M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "result" |), + Constant.int 1 + |) + ], + make_dict [] + |) ] + |) in + M.pure Constant.None_)) + ); + ( + "__rdivmod__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [ + M.get_name (| globals, locals_stack, "FixedUint" |); + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |), "__rdivmod__" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + make_tuple [ M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "result" |), + Constant.int 0 + |) + ], + make_dict [] + |); M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "result" |), + Constant.int 1 + |) + ], + make_dict [] + |) ] + |) in + M.pure Constant.None_)) + ); + ( + "__pow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right"; "modulo" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "modulo" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "modulo" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__pow__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "modulo" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "result" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "wrapping_pow", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right"; "modulo" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Return a new instance containing `self ** right (mod modulo)`. + + If omitted, `modulo` defaults to `Uint(self.MAX_VALUE) + 1`. + + Passing a `right` or `modulo` value greater than [`MAX_VALUE`] or + less than zero will raise a `ValueError`, even if the result would fit + in this integer type. + + [`MAX_VALUE`]: ref:ethereum.base_types.FixedUint.MAX_VALUE + " in + let _ := + (* if *) + M.if_then_else (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "modulo" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "modulo" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__pow__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "modulo" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rpow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left"; "modulo" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "modulo" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "modulo" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "modulo" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rpow__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "modulo" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__ipow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right"; "modulo" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__pow__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "modulo" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__and__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__and__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__or__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__or__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__xor__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "right" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "right" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__xor__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rxor__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "OverflowError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rxor__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__ixor__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__xor__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__invert__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__invert__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MAX_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rshift__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "shift_by" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "shift_by" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__class__" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rshift__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "shift_by" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "to_be_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this unsigned integer into its big endian representation, + omitting leading zero bytes. + " in + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "byte_length" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition U256 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedUint") + ]; + Klass.class_methods := [ + ( + "from_be_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "buffer" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts a sequence of bytes into a fixed sized unsigned integer + from its big endian representation. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "ValueError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "from_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |); + Constant.str "big" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "from_signed", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates an unsigned integer representing `value` using two's + complement. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "MAX_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; + Klass.methods := [ + ( + "to_be_bytes32", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this 256-bit unsigned integer into its big endian + representation with exactly 32 bytes. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes32" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + Constant.int 32; + Constant.str "big" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "to_signed", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decodes a signed integer from its two's complement representation. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition U32 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedUint") + ]; + Klass.class_methods := [ + ( + "from_le_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "buffer" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts a sequence of bytes into an arbitrarily sized unsigned integer + from its little endian representation. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |) + ], + make_dict [] + |), + Constant.int 4 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "ValueError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "from_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |); + Constant.str "little" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; + Klass.methods := [ + ( + "to_le_bytes4", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this fixed sized unsigned integer into its little endian + representation, with exactly 4 bytes. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes4" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + Constant.int 4; + Constant.str "little" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "to_le_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this fixed sized unsigned integer into its little endian + representation, in the fewest bytes possible. + " in + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "byte_length" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_length" |); + Constant.str "little" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition U64 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedUint") + ]; + Klass.class_methods := [ + ( + "from_le_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "buffer" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts a sequence of bytes into an arbitrarily sized unsigned integer + from its little endian representation. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |) + ], + make_dict [] + |), + Constant.int 8 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "ValueError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "from_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |); + Constant.str "little" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "from_be_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "buffer" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts a sequence of bytes into an unsigned 64 bit integer from its + big endian representation. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |) + ], + make_dict [] + |), + Constant.int 8 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "ValueError" |), + make_list [], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "from_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |); + Constant.str "big" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; + Klass.methods := [ + ( + "to_le_bytes8", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this fixed sized unsigned integer into its little endian + representation, with exactly 8 bytes. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes8" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + Constant.int 8; + Constant.str "little" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "to_le_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this fixed sized unsigned integer into its little endian + representation, in the fewest bytes possible. + " in + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "byte_length" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_length" |); + Constant.str "little" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition B : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "B" + ], + make_dict [] + |) +)). + +Definition FixedBytes : Value.t := make_klass {| + Klass.bases := [ + (globals, "bytes") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__new__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Create a new instance, ensuring the result has the correct length. + " in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [ + M.get_name (| globals, locals_stack, "FixedBytes" |); + M.get_name (| globals, locals_stack, "cls" |) + ], + make_dict [] + |), "__new__" |), + make_list_concat (| [ + make_list [ + M.get_name (| globals, locals_stack, "cls" |) + ]; + M.get_name (| globals, locals_stack, "args" |) + ] |), + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "LENGTH" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "ValueError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "result" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition Bytes0 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedBytes") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Bytes4 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedBytes") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Bytes8 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedBytes") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Bytes20 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedBytes") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Bytes32 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedBytes") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Bytes48 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedBytes") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Bytes64 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedBytes") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Bytes256 : Value.t := make_klass {| + Klass.bases := [ + (globals, "FixedBytes") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Bytes : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "bytes" |) +)). + +Definition expr_925 : Value.t := + Constant.str " +Sequence of bytes (octets) of arbitrary length. +". + +Definition _setattr_function : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "attr"; "value" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "getattr" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + Constant.str "_frozen"; + Constant.None_ + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "Exception" |), + make_list [ + Constant.str "Mutating frozen dataclasses is not allowed." + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "object" |), "__setattr__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "attr" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom _setattr_function_in_globals : + IsInGlobals globals "_setattr_function" (make_function _setattr_function). + +Definition _delattr_function : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "attr" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "_frozen" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "Exception" |), + make_list [ + Constant.str "Mutating frozen dataclasses is not allowed." + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "object" |), "__delattr__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "attr" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom _delattr_function_in_globals : + IsInGlobals globals "_delattr_function" (make_function _delattr_function). + +Definition _make_init_function : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "f" ] in + ltac:(M.monadic ( +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "init_function" |) + |) in + M.pure Constant.None_)). + +Axiom _make_init_function_in_globals : + IsInGlobals globals "_make_init_function" (make_function _make_init_function). + +Definition slotted_freezable : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Monkey patches a dataclass so it can be frozen by setting `_frozen` to + `True` and uses `__slots__` for efficiency. + + Instances will be created frozen by default unless you pass `_frozen=False` + to `__init__`. + " in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__slots__" |), + BinOp.add (| + make_tuple [ Constant.str "_frozen" ], + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__annotations__" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__init__" |), + M.call (| + M.get_name (| globals, locals_stack, "_make_init_function" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__init__" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__setattr__" |), + M.get_name (| globals, locals_stack, "_setattr_function" |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__delattr__" |), + M.get_name (| globals, locals_stack, "_delattr_function" |) + |) in + let _ := M.return_ (| + M.call (| + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |) + ], + make_dict [] + |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__name__" |); + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__bases__" |); + M.call (| + M.get_name (| globals, locals_stack, "dict" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__dict__" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom slotted_freezable_in_globals : + IsInGlobals globals "slotted_freezable" (make_function slotted_freezable). + +Definition S : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "S" + ], + make_dict [] + |) +)). + +Definition modify : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Create a copy of `obj` (which must be [`@slotted_freezable`]), and modify + it by applying `f`. The returned copy will be frozen. + + [`@slotted_freezable`]: ref:ethereum.base_types.slotted_freezable + " in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "is_dataclass" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.get_name (| globals, locals_stack, "SlottedFreezable" |) + ], + make_dict [] + |) |) in + let _ := M.assign_local (| + "new_obj" , + M.call (| + M.get_name (| globals, locals_stack, "replace" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + M.get_name (| globals, locals_stack, "new_obj" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "new_obj" |), "_frozen" |), + Constant.bool true + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "new_obj" |) + |) in + M.pure Constant.None_)). + +Axiom modify_in_globals : + IsInGlobals globals "modify" (make_function modify). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/__init__.md new file mode 100644 index 00000000..882ee4f5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/__init__.md @@ -0,0 +1,31 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 12244000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/blocks.md new file mode 100644 index 00000000..e0524a93 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/blocks.md @@ -0,0 +1,93 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Bloom : + IsImported globals "ethereum.berlin.fork_types" "Bloom". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". + +Axiom ethereum_berlin_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.berlin.transactions" "LegacyTransaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/bloom.md new file mode 100644 index 00000000..cdb0abfc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". + +Axiom ethereum_berlin_fork_types_imports_Bloom : + IsImported globals "ethereum.berlin.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/fork.md new file mode 100644 index 00000000..790deef5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/fork.md @@ -0,0 +1,3143 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_imports_vm : + IsImported globals "ethereum.berlin" "vm". + +Axiom ethereum_berlin_blocks_imports_Block : + IsImported globals "ethereum.berlin.blocks" "Block". +Axiom ethereum_berlin_blocks_imports_Header : + IsImported globals "ethereum.berlin.blocks" "Header". +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". +Axiom ethereum_berlin_blocks_imports_Receipt : + IsImported globals "ethereum.berlin.blocks" "Receipt". + +Axiom ethereum_berlin_bloom_imports_logs_bloom : + IsImported globals "ethereum.berlin.bloom" "logs_bloom". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Bloom : + IsImported globals "ethereum.berlin.fork_types" "Bloom". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". + +Axiom ethereum_berlin_state_imports_State : + IsImported globals "ethereum.berlin.state" "State". +Axiom ethereum_berlin_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.berlin.state" "account_exists_and_is_empty". +Axiom ethereum_berlin_state_imports_create_ether : + IsImported globals "ethereum.berlin.state" "create_ether". +Axiom ethereum_berlin_state_imports_destroy_account : + IsImported globals "ethereum.berlin.state" "destroy_account". +Axiom ethereum_berlin_state_imports_get_account : + IsImported globals "ethereum.berlin.state" "get_account". +Axiom ethereum_berlin_state_imports_increment_nonce : + IsImported globals "ethereum.berlin.state" "increment_nonce". +Axiom ethereum_berlin_state_imports_set_account_balance : + IsImported globals "ethereum.berlin.state" "set_account_balance". +Axiom ethereum_berlin_state_imports_state_root : + IsImported globals "ethereum.berlin.state" "state_root". + +Axiom ethereum_berlin_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.berlin.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_berlin_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.berlin.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_berlin_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.berlin.transactions" "TX_BASE_COST". +Axiom ethereum_berlin_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.berlin.transactions" "TX_CREATE_COST". +Axiom ethereum_berlin_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.berlin.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_berlin_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.berlin.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_berlin_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.berlin.transactions" "AccessListTransaction". +Axiom ethereum_berlin_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.berlin.transactions" "LegacyTransaction". +Axiom ethereum_berlin_transactions_imports_Transaction : + IsImported globals "ethereum.berlin.transactions" "Transaction". +Axiom ethereum_berlin_transactions_imports_decode_transaction : + IsImported globals "ethereum.berlin.transactions" "decode_transaction". +Axiom ethereum_berlin_transactions_imports_encode_transaction : + IsImported globals "ethereum.berlin.transactions" "encode_transaction". + +Axiom ethereum_berlin_trie_imports_Trie : + IsImported globals "ethereum.berlin.trie" "Trie". +Axiom ethereum_berlin_trie_imports_root : + IsImported globals "ethereum.berlin.trie" "root". +Axiom ethereum_berlin_trie_imports_trie_set : + IsImported globals "ethereum.berlin.trie" "trie_set". + +Axiom ethereum_berlin_utils_message_imports_prepare_message : + IsImported globals "ethereum.berlin.utils.message" "prepare_message". + +Axiom ethereum_berlin_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.berlin.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 9000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |); + M.get_name (| globals, locals_stack, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "map" |), + make_list [ + M.get_name (| globals, locals_stack, "decode_transaction" |); + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "encode_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "_address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |), + M.get_name (| globals, locals_stack, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_2930_in_globals : + IsInGlobals globals "signing_hash_2930" (make_function signing_hash_2930). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/fork_types.md new file mode 100644 index 00000000..1b60716d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/state.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/state.md new file mode 100644 index 00000000..383c2922 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/state.md @@ -0,0 +1,1391 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_berlin_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.berlin.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_berlin_fork_types_imports_Account : + IsImported globals "ethereum.berlin.fork_types" "Account". +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". + +Axiom ethereum_berlin_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.berlin.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_berlin_trie_imports_Trie : + IsImported globals "ethereum.berlin.trie" "Trie". +Axiom ethereum_berlin_trie_imports_copy_trie : + IsImported globals "ethereum.berlin.trie" "copy_trie". +Axiom ethereum_berlin_trie_imports_root : + IsImported globals "ethereum.berlin.trie" "root". +Axiom ethereum_berlin_trie_imports_trie_get : + IsImported globals "ethereum.berlin.trie" "trie_get". +Axiom ethereum_berlin_trie_imports_trie_set : + IsImported globals "ethereum.berlin.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom mark_account_created_in_globals : + IsInGlobals globals "mark_account_created" (make_function mark_account_created). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "_" |); M.get_name (| globals, locals_stack, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "original_account_trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "original_value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "original_value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_original_in_globals : + IsInGlobals globals "get_storage_original" (make_function get_storage_original). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/transactions.md new file mode 100644 index 00000000..9306e1bb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/transactions.md @@ -0,0 +1,235 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AccessListTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "AccessListTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_transaction_in_globals : + IsInGlobals globals "encode_transaction" (make_function encode_transaction). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom decode_transaction_in_globals : + IsInGlobals globals "decode_transaction" (make_function decode_transaction). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/trie.md new file mode 100644 index 00000000..a61bd175 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/trie.md @@ -0,0 +1,1645 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_muir_glacier_imports_trie : + IsImported globals "ethereum.muir_glacier" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_berlin_blocks_imports_Receipt : + IsImported globals "ethereum.berlin.blocks" "Receipt". + +Axiom ethereum_berlin_fork_types_imports_Account : + IsImported globals "ethereum.berlin.fork_types" "Account". +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". +Axiom ethereum_berlin_fork_types_imports_encode_account : + IsImported globals "ethereum.berlin.fork_types" "encode_account". + +Axiom ethereum_berlin_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.berlin.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/__init__.md new file mode 100644 index 00000000..733ea8f1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/address.md new file mode 100644 index 00000000..b8c642e1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this berlin version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/hexadecimal.md new file mode 100644 index 00000000..669e01a4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Berlin types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Bloom : + IsImported globals "ethereum.berlin.fork_types" "Bloom". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/message.md new file mode 100644 index 00000000..a8200250 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/utils/message.md @@ -0,0 +1,278 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_state_imports_get_account : + IsImported globals "ethereum.berlin.state" "get_account". + +Axiom ethereum_berlin_vm_imports_Environment : + IsImported globals "ethereum.berlin.vm" "Environment". +Axiom ethereum_berlin_vm_imports_Message : + IsImported globals "ethereum.berlin.vm" "Message". + +Axiom ethereum_berlin_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_berlin_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.berlin.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, locals_stack, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/__init__.md new file mode 100644 index 00000000..df86efb5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/__init__.md @@ -0,0 +1,273 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_state_imports_State : + IsImported globals "ethereum.berlin.state" "State". +Axiom ethereum_berlin_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.berlin.state" "account_exists_and_is_empty". + +Axiom ethereum_berlin_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/exceptions.md new file mode 100644 index 00000000..37d54c95 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/exceptions.md @@ -0,0 +1,171 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidParameter : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/gas.md new file mode 100644 index 00000000..38795260 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/gas.md @@ -0,0 +1,948 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/__init__.md new file mode 100644 index 00000000..a869c36c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_berlin_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.berlin.vm.instructions" "arithmetic". + +Axiom ethereum_berlin_vm_instructions_imports_bitwise : + IsImported globals "ethereum.berlin.vm.instructions" "bitwise". + +Axiom ethereum_berlin_vm_instructions_imports_block : + IsImported globals "ethereum.berlin.vm.instructions" "block". + +Axiom ethereum_berlin_vm_instructions_imports_comparison : + IsImported globals "ethereum.berlin.vm.instructions" "comparison". + +Axiom ethereum_berlin_vm_instructions_imports_control_flow : + IsImported globals "ethereum.berlin.vm.instructions" "control_flow". + +Axiom ethereum_berlin_vm_instructions_imports_environment : + IsImported globals "ethereum.berlin.vm.instructions" "environment". + +Axiom ethereum_berlin_vm_instructions_imports_keccak : + IsImported globals "ethereum.berlin.vm.instructions" "keccak". + +Axiom ethereum_berlin_vm_instructions_imports_log : + IsImported globals "ethereum.berlin.vm.instructions" "log". + +Axiom ethereum_berlin_vm_instructions_imports_memory : + IsImported globals "ethereum.berlin.vm.instructions" "memory". + +Axiom ethereum_berlin_vm_instructions_imports_stack : + IsImported globals "ethereum.berlin.vm.instructions" "stack". + +Axiom ethereum_berlin_vm_instructions_imports_storage : + IsImported globals "ethereum.berlin.vm.instructions" "storage". + +Axiom ethereum_berlin_vm_instructions_imports_system : + IsImported globals "ethereum.berlin.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/arithmetic.md new file mode 100644 index 00000000..bfe369cf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.berlin.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_berlin_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_berlin_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_LOW". +Axiom ethereum_berlin_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.berlin.vm.gas" "GAS_MID". +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/bitwise.md new file mode 100644 index 00000000..96420711 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/block.md new file mode 100644 index 00000000..3b1c9b7d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/block.md @@ -0,0 +1,426 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom chain_id_in_globals : + IsInGlobals globals "chain_id" (make_function chain_id). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/comparison.md new file mode 100644 index 00000000..38b62367 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/control_flow.md new file mode 100644 index 00000000..628e87f8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.berlin.vm.gas" "GAS_HIGH". +Axiom ethereum_berlin_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.berlin.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_berlin_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.berlin.vm.gas" "GAS_MID". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.berlin.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/environment.md new file mode 100644 index 00000000..d9990ea5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/environment.md @@ -0,0 +1,1564 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.berlin.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_berlin_state_imports_get_account : + IsImported globals "ethereum.berlin.state" "get_account". + +Axiom ethereum_berlin_utils_address_imports_to_address : + IsImported globals "ethereum.berlin.utils.address" "to_address". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". +Axiom ethereum_berlin_vm_memory_imports_memory_write : + IsImported globals "ethereum.berlin.vm.memory" "memory_write". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.berlin.vm.gas" "GAS_COPY". +Axiom ethereum_berlin_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.berlin.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_berlin_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.berlin.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom self_balance_in_globals : + IsInGlobals globals "self_balance" (make_function self_balance). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/keccak.md new file mode 100644 index 00000000..1f277d3c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.berlin.vm.gas" "GAS_KECCAK256". +Axiom ethereum_berlin_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.berlin.vm.memory" "memory_read_bytes". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/log.md new file mode 100644 index 00000000..dbe76091 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.berlin.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_berlin_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.berlin.vm.gas" "GAS_LOG". +Axiom ethereum_berlin_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.berlin.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_berlin_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.berlin.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.berlin.vm.memory" "memory_read_bytes". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/memory.md new file mode 100644 index 00000000..5661523c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.berlin.vm.memory" "memory_read_bytes". +Axiom ethereum_berlin_vm_memory_imports_memory_write : + IsImported globals "ethereum.berlin.vm.memory" "memory_write". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/stack.md new file mode 100644 index 00000000..cb0352f7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". +Axiom ethereum_berlin_vm_imports_stack : + IsImported globals "ethereum.berlin.vm" "stack". + +Axiom ethereum_berlin_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.berlin.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/storage.md new file mode 100644 index 00000000..298f7299 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/storage.md @@ -0,0 +1,512 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_state_imports_get_storage : + IsImported globals "ethereum.berlin.state" "get_storage". +Axiom ethereum_berlin_state_imports_get_storage_original : + IsImported globals "ethereum.berlin.state" "get_storage_original". +Axiom ethereum_berlin_state_imports_set_storage : + IsImported globals "ethereum.berlin.state" "set_storage". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfGasError". +Axiom ethereum_berlin_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.berlin.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_berlin_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.berlin.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_berlin_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_berlin_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.berlin.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_berlin_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.berlin.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_berlin_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_berlin_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/system.md new file mode 100644 index 00000000..70df954f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/instructions/system.md @@ -0,0 +1,2329 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.berlin.state" "account_exists_and_is_empty". +Axiom ethereum_berlin_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.berlin.state" "account_has_code_or_nonce". +Axiom ethereum_berlin_state_imports_get_account : + IsImported globals "ethereum.berlin.state" "get_account". +Axiom ethereum_berlin_state_imports_increment_nonce : + IsImported globals "ethereum.berlin.state" "increment_nonce". +Axiom ethereum_berlin_state_imports_is_account_alive : + IsImported globals "ethereum.berlin.state" "is_account_alive". +Axiom ethereum_berlin_state_imports_set_account_balance : + IsImported globals "ethereum.berlin.state" "set_account_balance". + +Axiom ethereum_berlin_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.berlin.utils.address" "compute_contract_address". +Axiom ethereum_berlin_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.berlin.utils.address" "compute_create2_contract_address". +Axiom ethereum_berlin_utils_address_imports_to_address : + IsImported globals "ethereum.berlin.utils.address" "to_address". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". +Axiom ethereum_berlin_vm_imports_Message : + IsImported globals "ethereum.berlin.vm" "Message". +Axiom ethereum_berlin_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.berlin.vm" "incorporate_child_on_error". +Axiom ethereum_berlin_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.berlin.vm" "incorporate_child_on_success". + +Axiom ethereum_berlin_vm_exceptions_imports_Revert : + IsImported globals "ethereum.berlin.vm.exceptions" "Revert". +Axiom ethereum_berlin_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.berlin.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_berlin_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_berlin_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_CREATE". +Axiom ethereum_berlin_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_berlin_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.berlin.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_berlin_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.berlin.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_berlin_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.berlin.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_berlin_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.berlin.vm.gas" "GAS_ZERO". +Axiom ethereum_berlin_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.berlin.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.berlin.vm.gas" "calculate_message_call_gas". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". +Axiom ethereum_berlin_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.berlin.vm.gas" "max_message_call_gas". + +Axiom ethereum_berlin_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.berlin.vm.memory" "memory_read_bytes". +Axiom ethereum_berlin_vm_memory_imports_memory_write : + IsImported globals "ethereum.berlin.vm.memory" "memory_write". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "beneficiary" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/interpreter.md new file mode 100644 index 00000000..c192c0e2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/interpreter.md @@ -0,0 +1,693 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.berlin.state" "account_exists_and_is_empty". +Axiom ethereum_berlin_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.berlin.state" "account_has_code_or_nonce". +Axiom ethereum_berlin_state_imports_begin_transaction : + IsImported globals "ethereum.berlin.state" "begin_transaction". +Axiom ethereum_berlin_state_imports_commit_transaction : + IsImported globals "ethereum.berlin.state" "commit_transaction". +Axiom ethereum_berlin_state_imports_destroy_storage : + IsImported globals "ethereum.berlin.state" "destroy_storage". +Axiom ethereum_berlin_state_imports_increment_nonce : + IsImported globals "ethereum.berlin.state" "increment_nonce". +Axiom ethereum_berlin_state_imports_mark_account_created : + IsImported globals "ethereum.berlin.state" "mark_account_created". +Axiom ethereum_berlin_state_imports_move_ether : + IsImported globals "ethereum.berlin.state" "move_ether". +Axiom ethereum_berlin_state_imports_rollback_transaction : + IsImported globals "ethereum.berlin.state" "rollback_transaction". +Axiom ethereum_berlin_state_imports_set_code : + IsImported globals "ethereum.berlin.state" "set_code". +Axiom ethereum_berlin_state_imports_touch_account : + IsImported globals "ethereum.berlin.state" "touch_account". + +Axiom ethereum_berlin_vm_imports_Message : + IsImported globals "ethereum.berlin.vm" "Message". + +Axiom ethereum_berlin_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.berlin.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_berlin_vm_imports_Environment : + IsImported globals "ethereum.berlin.vm" "Environment". +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.berlin.vm.exceptions" "AddressCollision". +Axiom ethereum_berlin_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.berlin.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_berlin_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.berlin.vm.exceptions" "InvalidOpcode". +Axiom ethereum_berlin_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfGasError". +Axiom ethereum_berlin_vm_exceptions_imports_Revert : + IsImported globals "ethereum.berlin.vm.exceptions" "Revert". +Axiom ethereum_berlin_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.berlin.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_berlin_vm_instructions_imports_Ops : + IsImported globals "ethereum.berlin.vm.instructions" "Ops". +Axiom ethereum_berlin_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.berlin.vm.instructions" "op_implementation". + +Axiom ethereum_berlin_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.berlin.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/memory.md new file mode 100644 index 00000000..f43f39ab --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..bd18cbb6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/__init__.md @@ -0,0 +1,124 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_berlin_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.berlin.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..31a1d655 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". + +Axiom ethereum_berlin_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..2ce05eb0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,144 @@ +# ๐Ÿ“ blake2f.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/blake2f.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.precompiled_contracts.blake2f". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.berlin.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, locals_stack, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, locals_stack, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, locals_stack, "rounds" |); + M.get_name (| globals, locals_stack, "h" |); + M.get_name (| globals, locals_stack, "m" |); + M.get_name (| globals, locals_stack, "t_0" |); + M.get_name (| globals, locals_stack, "t_1" |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom blake2f_in_globals : + IsInGlobals globals "blake2f" (make_function blake2f). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..fd83a39d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.berlin.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..de0c45c1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.berlin.vm.gas" "GAS_IDENTITY". +Axiom ethereum_berlin_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..abe72385 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/mapping.md @@ -0,0 +1,80 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_berlin_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_berlin_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_berlin_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_berlin_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_berlin_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_berlin_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_berlin_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_berlin_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_berlin_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..2229cef0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/modexp.md @@ -0,0 +1,700 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |); + M.get_name (| globals, locals_stack, "exp_length" |); + M.get_name (| globals, locals_stack, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Axiom complexity_in_globals : + IsInGlobals globals "complexity" (make_function complexity). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, locals_stack, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, locals_stack, "length_part" |), + M.get_name (| globals, locals_stack, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "count" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom iterations_in_globals : + IsInGlobals globals "iterations" (make_function iterations). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, locals_stack, "complexity" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, locals_stack, "iterations" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |); + M.get_name (| globals, locals_stack, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "multiplication_complexity" |), + M.get_name (| globals, locals_stack, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom gas_cost_in_globals : + IsInGlobals globals "gas_cost" (make_function gas_cost). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..de5d9db2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.berlin.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_berlin_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..f041a4ef --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.berlin.vm.gas" "GAS_SHA256". +Axiom ethereum_berlin_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/runtime.md new file mode 100644 index 00000000..e78d6e34 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_vm_instructions_imports_Ops : + IsImported globals "ethereum.berlin.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/stack.md new file mode 100644 index 00000000..86de8d5d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/berlin/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/berlin/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.berlin.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_berlin_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.berlin.vm.exceptions" "StackOverflowError". +Axiom ethereum_berlin_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.berlin.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/__init__.md new file mode 100644 index 00000000..b474a909 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/__init__.md @@ -0,0 +1,31 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 4370000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/blocks.md new file mode 100644 index 00000000..d9e2abc7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/blocks.md @@ -0,0 +1,91 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Bloom : + IsImported globals "ethereum.byzantium.fork_types" "Bloom". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". + +Axiom ethereum_byzantium_transactions_imports_Transaction : + IsImported globals "ethereum.byzantium.transactions" "Transaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/bloom.md new file mode 100644 index 00000000..861cfa1e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". + +Axiom ethereum_byzantium_fork_types_imports_Bloom : + IsImported globals "ethereum.byzantium.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/fork.md new file mode 100644 index 00000000..6ba983b1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/fork.md @@ -0,0 +1,2862 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_imports_vm : + IsImported globals "ethereum.byzantium" "vm". + +Axiom ethereum_byzantium_blocks_imports_Block : + IsImported globals "ethereum.byzantium.blocks" "Block". +Axiom ethereum_byzantium_blocks_imports_Header : + IsImported globals "ethereum.byzantium.blocks" "Header". +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". +Axiom ethereum_byzantium_blocks_imports_Receipt : + IsImported globals "ethereum.byzantium.blocks" "Receipt". + +Axiom ethereum_byzantium_bloom_imports_logs_bloom : + IsImported globals "ethereum.byzantium.bloom" "logs_bloom". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Bloom : + IsImported globals "ethereum.byzantium.fork_types" "Bloom". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". + +Axiom ethereum_byzantium_state_imports_State : + IsImported globals "ethereum.byzantium.state" "State". +Axiom ethereum_byzantium_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.byzantium.state" "account_exists_and_is_empty". +Axiom ethereum_byzantium_state_imports_create_ether : + IsImported globals "ethereum.byzantium.state" "create_ether". +Axiom ethereum_byzantium_state_imports_destroy_account : + IsImported globals "ethereum.byzantium.state" "destroy_account". +Axiom ethereum_byzantium_state_imports_get_account : + IsImported globals "ethereum.byzantium.state" "get_account". +Axiom ethereum_byzantium_state_imports_increment_nonce : + IsImported globals "ethereum.byzantium.state" "increment_nonce". +Axiom ethereum_byzantium_state_imports_set_account_balance : + IsImported globals "ethereum.byzantium.state" "set_account_balance". +Axiom ethereum_byzantium_state_imports_state_root : + IsImported globals "ethereum.byzantium.state" "state_root". + +Axiom ethereum_byzantium_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.byzantium.transactions" "TX_BASE_COST". +Axiom ethereum_byzantium_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.byzantium.transactions" "TX_CREATE_COST". +Axiom ethereum_byzantium_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.byzantium.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_byzantium_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.byzantium.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_byzantium_transactions_imports_Transaction : + IsImported globals "ethereum.byzantium.transactions" "Transaction". + +Axiom ethereum_byzantium_trie_imports_Trie : + IsImported globals "ethereum.byzantium.trie" "Trie". +Axiom ethereum_byzantium_trie_imports_root : + IsImported globals "ethereum.byzantium.trie" "root". +Axiom ethereum_byzantium_trie_imports_trie_set : + IsImported globals "ethereum.byzantium.trie" "trie_set". + +Axiom ethereum_byzantium_utils_message_imports_prepare_message : + IsImported globals "ethereum.byzantium.utils.message" "prepare_message". + +Axiom ethereum_byzantium_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.byzantium.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 3, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 3000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |); + M.get_name (| globals, locals_stack, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "v" |); M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/fork_types.md new file mode 100644 index 00000000..3602843e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/state.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/state.md new file mode 100644 index 00000000..c0c70de0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/state.md @@ -0,0 +1,1215 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_byzantium_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.byzantium.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_byzantium_fork_types_imports_Account : + IsImported globals "ethereum.byzantium.fork_types" "Account". +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". + +Axiom ethereum_byzantium_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.byzantium.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_byzantium_trie_imports_Trie : + IsImported globals "ethereum.byzantium.trie" "Trie". +Axiom ethereum_byzantium_trie_imports_copy_trie : + IsImported globals "ethereum.byzantium.trie" "copy_trie". +Axiom ethereum_byzantium_trie_imports_root : + IsImported globals "ethereum.byzantium.trie" "root". +Axiom ethereum_byzantium_trie_imports_trie_get : + IsImported globals "ethereum.byzantium.trie" "trie_get". +Axiom ethereum_byzantium_trie_imports_trie_set : + IsImported globals "ethereum.byzantium.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/transactions.md new file mode 100644 index 00000000..515050d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/transactions.md @@ -0,0 +1,63 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/trie.md new file mode 100644 index 00000000..e8e4b50b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/trie.md @@ -0,0 +1,1639 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_spurious_dragon_imports_trie : + IsImported globals "ethereum.spurious_dragon" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_byzantium_blocks_imports_Receipt : + IsImported globals "ethereum.byzantium.blocks" "Receipt". + +Axiom ethereum_byzantium_fork_types_imports_Account : + IsImported globals "ethereum.byzantium.fork_types" "Account". +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". +Axiom ethereum_byzantium_fork_types_imports_encode_account : + IsImported globals "ethereum.byzantium.fork_types" "encode_account". + +Axiom ethereum_byzantium_transactions_imports_Transaction : + IsImported globals "ethereum.byzantium.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Receipt" |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/__init__.md new file mode 100644 index 00000000..e0d2db12 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/address.md new file mode 100644 index 00000000..50d64413 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/address.md @@ -0,0 +1,160 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this byzantium version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/hexadecimal.md new file mode 100644 index 00000000..766feb0c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Byzantium types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Bloom : + IsImported globals "ethereum.byzantium.fork_types" "Bloom". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/message.md new file mode 100644 index 00000000..5ae21305 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/utils/message.md @@ -0,0 +1,224 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_state_imports_get_account : + IsImported globals "ethereum.byzantium.state" "get_account". + +Axiom ethereum_byzantium_vm_imports_Environment : + IsImported globals "ethereum.byzantium.vm" "Environment". +Axiom ethereum_byzantium_vm_imports_Message : + IsImported globals "ethereum.byzantium.vm" "Message". + +Axiom ethereum_byzantium_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.byzantium.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/__init__.md new file mode 100644 index 00000000..2f4c6fe1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/__init__.md @@ -0,0 +1,255 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_state_imports_State : + IsImported globals "ethereum.byzantium.state" "State". +Axiom ethereum_byzantium_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.byzantium.state" "account_exists_and_is_empty". + +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/exceptions.md new file mode 100644 index 00000000..31a44777 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/exceptions.md @@ -0,0 +1,161 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/gas.md new file mode 100644 index 00000000..82838bfc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/gas.md @@ -0,0 +1,938 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.byzantium.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/__init__.md new file mode 100644 index 00000000..d94072ff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_byzantium_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.byzantium.vm.instructions" "arithmetic". + +Axiom ethereum_byzantium_vm_instructions_imports_bitwise : + IsImported globals "ethereum.byzantium.vm.instructions" "bitwise". + +Axiom ethereum_byzantium_vm_instructions_imports_block : + IsImported globals "ethereum.byzantium.vm.instructions" "block". + +Axiom ethereum_byzantium_vm_instructions_imports_comparison : + IsImported globals "ethereum.byzantium.vm.instructions" "comparison". + +Axiom ethereum_byzantium_vm_instructions_imports_control_flow : + IsImported globals "ethereum.byzantium.vm.instructions" "control_flow". + +Axiom ethereum_byzantium_vm_instructions_imports_environment : + IsImported globals "ethereum.byzantium.vm.instructions" "environment". + +Axiom ethereum_byzantium_vm_instructions_imports_keccak : + IsImported globals "ethereum.byzantium.vm.instructions" "keccak". + +Axiom ethereum_byzantium_vm_instructions_imports_log : + IsImported globals "ethereum.byzantium.vm.instructions" "log". + +Axiom ethereum_byzantium_vm_instructions_imports_memory : + IsImported globals "ethereum.byzantium.vm.instructions" "memory". + +Axiom ethereum_byzantium_vm_instructions_imports_stack : + IsImported globals "ethereum.byzantium.vm.instructions" "stack". + +Axiom ethereum_byzantium_vm_instructions_imports_storage : + IsImported globals "ethereum.byzantium.vm.instructions" "storage". + +Axiom ethereum_byzantium_vm_instructions_imports_system : + IsImported globals "ethereum.byzantium.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/arithmetic.md new file mode 100644 index 00000000..4aa8adef --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_byzantium_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_LOW". +Axiom ethereum_byzantium_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_MID". +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/bitwise.md new file mode 100644 index 00000000..c95cdf5a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/bitwise.md @@ -0,0 +1,400 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/block.md new file mode 100644 index 00000000..61cf7414 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/block.md @@ -0,0 +1,380 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/comparison.md new file mode 100644 index 00000000..e126c186 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/control_flow.md new file mode 100644 index 00000000..26205235 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_HIGH". +Axiom ethereum_byzantium_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_byzantium_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_MID". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.byzantium.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/environment.md new file mode 100644 index 00000000..62d1012d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/environment.md @@ -0,0 +1,1279 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_state_imports_get_account : + IsImported globals "ethereum.byzantium.state" "get_account". + +Axiom ethereum_byzantium_utils_address_imports_to_address : + IsImported globals "ethereum.byzantium.utils.address" "to_address". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". +Axiom ethereum_byzantium_vm_memory_imports_memory_write : + IsImported globals "ethereum.byzantium.vm.memory" "memory_write". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.byzantium.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BALANCE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_COPY". +Axiom ethereum_byzantium_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_byzantium_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/keccak.md new file mode 100644 index 00000000..24e62970 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_KECCAK256". +Axiom ethereum_byzantium_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.byzantium.vm.memory" "memory_read_bytes". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/log.md new file mode 100644 index 00000000..b93419d1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.byzantium.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_LOG". +Axiom ethereum_byzantium_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_byzantium_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.byzantium.vm.memory" "memory_read_bytes". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/memory.md new file mode 100644 index 00000000..cd457920 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.byzantium.vm.memory" "memory_read_bytes". +Axiom ethereum_byzantium_vm_memory_imports_memory_write : + IsImported globals "ethereum.byzantium.vm.memory" "memory_write". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/stack.md new file mode 100644 index 00000000..185ba2b3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". +Axiom ethereum_byzantium_vm_imports_stack : + IsImported globals "ethereum.byzantium.vm" "stack". + +Axiom ethereum_byzantium_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.byzantium.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/storage.md new file mode 100644 index 00000000..092b6442 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/storage.md @@ -0,0 +1,265 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_byzantium_state_imports_get_storage : + IsImported globals "ethereum.byzantium.state" "get_storage". +Axiom ethereum_byzantium_state_imports_set_storage : + IsImported globals "ethereum.byzantium.state" "set_storage". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.byzantium.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SLOAD". +Axiom ethereum_byzantium_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_byzantium_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_byzantium_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/system.md new file mode 100644 index 00000000..6e644bde --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/instructions/system.md @@ -0,0 +1,1985 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.byzantium.state" "account_exists_and_is_empty". +Axiom ethereum_byzantium_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.byzantium.state" "account_has_code_or_nonce". +Axiom ethereum_byzantium_state_imports_get_account : + IsImported globals "ethereum.byzantium.state" "get_account". +Axiom ethereum_byzantium_state_imports_increment_nonce : + IsImported globals "ethereum.byzantium.state" "increment_nonce". +Axiom ethereum_byzantium_state_imports_is_account_alive : + IsImported globals "ethereum.byzantium.state" "is_account_alive". +Axiom ethereum_byzantium_state_imports_set_account_balance : + IsImported globals "ethereum.byzantium.state" "set_account_balance". + +Axiom ethereum_byzantium_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.byzantium.utils.address" "compute_contract_address". +Axiom ethereum_byzantium_utils_address_imports_to_address : + IsImported globals "ethereum.byzantium.utils.address" "to_address". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". +Axiom ethereum_byzantium_vm_imports_Message : + IsImported globals "ethereum.byzantium.vm" "Message". +Axiom ethereum_byzantium_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.byzantium.vm" "incorporate_child_on_error". +Axiom ethereum_byzantium_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.byzantium.vm" "incorporate_child_on_success". + +Axiom ethereum_byzantium_vm_exceptions_imports_Revert : + IsImported globals "ethereum.byzantium.vm.exceptions" "Revert". +Axiom ethereum_byzantium_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.byzantium.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_CALL". +Axiom ethereum_byzantium_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_CREATE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_byzantium_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_byzantium_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_byzantium_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_ZERO". +Axiom ethereum_byzantium_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.byzantium.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_message_call_gas". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". +Axiom ethereum_byzantium_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.byzantium.vm.gas" "max_message_call_gas". + +Axiom ethereum_byzantium_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.byzantium.vm.memory" "memory_read_bytes". +Axiom ethereum_byzantium_vm_memory_imports_memory_write : + IsImported globals "ethereum.byzantium.vm.memory" "memory_write". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/interpreter.md new file mode 100644 index 00000000..3cbc0014 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/interpreter.md @@ -0,0 +1,677 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.byzantium.state" "account_exists_and_is_empty". +Axiom ethereum_byzantium_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.byzantium.state" "account_has_code_or_nonce". +Axiom ethereum_byzantium_state_imports_begin_transaction : + IsImported globals "ethereum.byzantium.state" "begin_transaction". +Axiom ethereum_byzantium_state_imports_commit_transaction : + IsImported globals "ethereum.byzantium.state" "commit_transaction". +Axiom ethereum_byzantium_state_imports_destroy_storage : + IsImported globals "ethereum.byzantium.state" "destroy_storage". +Axiom ethereum_byzantium_state_imports_increment_nonce : + IsImported globals "ethereum.byzantium.state" "increment_nonce". +Axiom ethereum_byzantium_state_imports_move_ether : + IsImported globals "ethereum.byzantium.state" "move_ether". +Axiom ethereum_byzantium_state_imports_rollback_transaction : + IsImported globals "ethereum.byzantium.state" "rollback_transaction". +Axiom ethereum_byzantium_state_imports_set_code : + IsImported globals "ethereum.byzantium.state" "set_code". +Axiom ethereum_byzantium_state_imports_touch_account : + IsImported globals "ethereum.byzantium.state" "touch_account". + +Axiom ethereum_byzantium_vm_imports_Message : + IsImported globals "ethereum.byzantium.vm" "Message". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_byzantium_vm_imports_Environment : + IsImported globals "ethereum.byzantium.vm" "Environment". +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.byzantium.vm.exceptions" "AddressCollision". +Axiom ethereum_byzantium_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.byzantium.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_byzantium_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.byzantium.vm.exceptions" "InvalidOpcode". +Axiom ethereum_byzantium_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.byzantium.vm.exceptions" "OutOfGasError". +Axiom ethereum_byzantium_vm_exceptions_imports_Revert : + IsImported globals "ethereum.byzantium.vm.exceptions" "Revert". +Axiom ethereum_byzantium_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.byzantium.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_byzantium_vm_instructions_imports_Ops : + IsImported globals "ethereum.byzantium.vm.instructions" "Ops". +Axiom ethereum_byzantium_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.byzantium.vm.instructions" "op_implementation". + +Axiom ethereum_byzantium_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.byzantium.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/memory.md new file mode 100644 index 00000000..f94d46cf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..96834b4b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/__init__.md @@ -0,0 +1,114 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_byzantium_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.byzantium.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..d741ecd2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". + +Axiom ethereum_byzantium_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.byzantium.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 500 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 40000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 80000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 100000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..9d930f9c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..ef92ef4c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_IDENTITY". +Axiom ethereum_byzantium_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..98da0b7d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/mapping.md @@ -0,0 +1,75 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_byzantium_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_byzantium_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_byzantium_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_byzantium_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_byzantium_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_byzantium_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_byzantium_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_byzantium_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..b31f4f5c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/modexp.md @@ -0,0 +1,560 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "exp_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.floor_div (| + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_mult_complexity" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "adjusted_exp_length" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition get_mult_complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Estimate the complexity of performing Karatsuba multiplication. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 64 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |), + Constant.int 4 + |), + BinOp.mult (| + Constant.int 96, + M.get_name (| globals, locals_stack, "x" |) + |) + |), + Constant.int 3072 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |), + Constant.int 16 + |), + BinOp.mult (| + Constant.int 480, + M.get_name (| globals, locals_stack, "x" |) + |) + |), + Constant.int 199680 + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_mult_complexity_in_globals : + IsInGlobals globals "get_mult_complexity" (make_function get_mult_complexity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..6f5eb6f8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_byzantium_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..c5383aa2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SHA256". +Axiom ethereum_byzantium_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/runtime.md new file mode 100644 index 00000000..197492c0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_vm_instructions_imports_Ops : + IsImported globals "ethereum.byzantium.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/stack.md new file mode 100644 index 00000000..fa438b28 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/byzantium/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/byzantium/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.byzantium.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.byzantium.vm.exceptions" "StackOverflowError". +Axiom ethereum_byzantium_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.byzantium.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/__init__.md new file mode 100644 index 00000000..4714be43 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/__init__.md @@ -0,0 +1,32 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByTimestamp : + IsImported globals "ethereum.fork_criteria" "ByTimestamp". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByTimestamp" |), + make_list [ + Constant.int 1710338135 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/blocks.md new file mode 100644 index 00000000..b6d38e9b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/blocks.md @@ -0,0 +1,104 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Bloom : + IsImported globals "ethereum.cancun.fork_types" "Bloom". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". + +Axiom ethereum_cancun_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.cancun.transactions" "LegacyTransaction". + +Definition Withdrawal : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/bloom.md new file mode 100644 index 00000000..c46db281 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". + +Axiom ethereum_cancun_fork_types_imports_Bloom : + IsImported globals "ethereum.cancun.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/fork.md new file mode 100644 index 00000000..45bf346b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/fork.md @@ -0,0 +1,3340 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_imports_vm : + IsImported globals "ethereum.cancun" "vm". + +Axiom ethereum_cancun_blocks_imports_Block : + IsImported globals "ethereum.cancun.blocks" "Block". +Axiom ethereum_cancun_blocks_imports_Header : + IsImported globals "ethereum.cancun.blocks" "Header". +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". +Axiom ethereum_cancun_blocks_imports_Receipt : + IsImported globals "ethereum.cancun.blocks" "Receipt". +Axiom ethereum_cancun_blocks_imports_Withdrawal : + IsImported globals "ethereum.cancun.blocks" "Withdrawal". + +Axiom ethereum_cancun_bloom_imports_logs_bloom : + IsImported globals "ethereum.cancun.bloom" "logs_bloom". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Bloom : + IsImported globals "ethereum.cancun.fork_types" "Bloom". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". +Axiom ethereum_cancun_fork_types_imports_VersionedHash : + IsImported globals "ethereum.cancun.fork_types" "VersionedHash". + +Axiom ethereum_cancun_state_imports_State : + IsImported globals "ethereum.cancun.state" "State". +Axiom ethereum_cancun_state_imports_TransientStorage : + IsImported globals "ethereum.cancun.state" "TransientStorage". +Axiom ethereum_cancun_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.cancun.state" "account_exists_and_is_empty". +Axiom ethereum_cancun_state_imports_destroy_account : + IsImported globals "ethereum.cancun.state" "destroy_account". +Axiom ethereum_cancun_state_imports_destroy_touched_empty_accounts : + IsImported globals "ethereum.cancun.state" "destroy_touched_empty_accounts". +Axiom ethereum_cancun_state_imports_get_account : + IsImported globals "ethereum.cancun.state" "get_account". +Axiom ethereum_cancun_state_imports_increment_nonce : + IsImported globals "ethereum.cancun.state" "increment_nonce". +Axiom ethereum_cancun_state_imports_process_withdrawal : + IsImported globals "ethereum.cancun.state" "process_withdrawal". +Axiom ethereum_cancun_state_imports_set_account_balance : + IsImported globals "ethereum.cancun.state" "set_account_balance". +Axiom ethereum_cancun_state_imports_state_root : + IsImported globals "ethereum.cancun.state" "state_root". + +Axiom ethereum_cancun_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.cancun.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_cancun_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.cancun.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_cancun_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.cancun.transactions" "TX_BASE_COST". +Axiom ethereum_cancun_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.cancun.transactions" "TX_CREATE_COST". +Axiom ethereum_cancun_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.cancun.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_cancun_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.cancun.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_cancun_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.cancun.transactions" "AccessListTransaction". +Axiom ethereum_cancun_transactions_imports_BlobTransaction : + IsImported globals "ethereum.cancun.transactions" "BlobTransaction". +Axiom ethereum_cancun_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.cancun.transactions" "FeeMarketTransaction". +Axiom ethereum_cancun_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.cancun.transactions" "LegacyTransaction". +Axiom ethereum_cancun_transactions_imports_Transaction : + IsImported globals "ethereum.cancun.transactions" "Transaction". +Axiom ethereum_cancun_transactions_imports_decode_transaction : + IsImported globals "ethereum.cancun.transactions" "decode_transaction". +Axiom ethereum_cancun_transactions_imports_encode_transaction : + IsImported globals "ethereum.cancun.transactions" "encode_transaction". + +Axiom ethereum_cancun_trie_imports_Trie : + IsImported globals "ethereum.cancun.trie" "Trie". +Axiom ethereum_cancun_trie_imports_root : + IsImported globals "ethereum.cancun.trie" "root". +Axiom ethereum_cancun_trie_imports_trie_set : + IsImported globals "ethereum.cancun.trie" "trie_set". + +Axiom ethereum_cancun_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.cancun.utils.hexadecimal" "hex_to_address". + +Axiom ethereum_cancun_utils_message_imports_prepare_message : + IsImported globals "ethereum.cancun.utils.message" "prepare_message". + +Axiom ethereum_cancun_vm_imports_Message : + IsImported globals "ethereum.cancun.vm" "Message". + +Axiom ethereum_cancun_vm_gas_imports_calculate_blob_gas_price : + IsImported globals "ethereum.cancun.vm.gas" "calculate_blob_gas_price". +Axiom ethereum_cancun_vm_gas_imports_calculate_data_fee : + IsImported globals "ethereum.cancun.vm.gas" "calculate_data_fee". +Axiom ethereum_cancun_vm_gas_imports_calculate_excess_blob_gas : + IsImported globals "ethereum.cancun.vm.gas" "calculate_excess_blob_gas". +Axiom ethereum_cancun_vm_gas_imports_calculate_total_blob_gas : + IsImported globals "ethereum.cancun.vm.gas" "calculate_total_blob_gas". +Axiom ethereum_cancun_vm_gas_imports_init_code_cost : + IsImported globals "ethereum.cancun.vm.gas" "init_code_cost". + +Axiom ethereum_cancun_vm_interpreter_imports_MAX_CODE_SIZE : + IsImported globals "ethereum.cancun.vm.interpreter" "MAX_CODE_SIZE". +Axiom ethereum_cancun_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.cancun.vm.interpreter" "process_message_call". + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition SYSTEM_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0xfffffffffffffffffffffffffffffffffffffffe" + ], + make_dict [] + |) +)). + +Definition BEACON_ROOTS_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" + ], + make_dict [] + |) +)). + +Definition SYSTEM_TRANSACTION_GAS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30000000 + ], + make_dict [] + |) +)). + +Definition MAX_BLOB_GAS_PER_BLOCK : Value.t := M.run ltac:(M.monadic ( + Constant.int 786432 +)). + +Definition VERSIONED_HASH_VERSION_KZG : Value.t := M.run ltac:(M.monadic ( + Constant.bytes "01" +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.assign_local (| + "excess_blob_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_excess_blob_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "excess_blob_gas" |), + M.get_name (| globals, locals_stack, "excess_blob_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |), + make_tuple [ ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "prev_randao" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "withdrawals" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_beacon_block_root" |); + M.get_name (| globals, locals_stack, "excess_blob_gas" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "withdrawals_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "withdrawals_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "blob_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "blob_gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_limit" |); + M.get_name (| globals, locals_stack, "parent_gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_target" |), + M.get_name (| globals, locals_stack, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_base_fee_per_gas_in_globals : + IsInGlobals globals "calculate_base_fee_per_gas" (make_function calculate_base_fee_per_gas). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |), + Constant.bytes "0000000000000000" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "tx"; "gas_available"; "chain_id"; "base_fee_per_gas"; "excess_blob_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) + ], + make_dict [] + |), + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "MAX_CODE_SIZE" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); M.get_name (| globals, locals_stack, "BlobTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) in + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "blob_versioned_hashes" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "blob_versioned_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "blob_versioned_hashes" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.slice (| + M.get_name (| globals, locals_stack, "blob_versioned_hash" |), + Constant.int 0, + Constant.int 1, + Constant.None_ + |), + M.get_name (| globals, locals_stack, "VERSIONED_HASH_VERSION_KZG" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_blob_gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_blob_gas_price" |), + make_list [ + M.get_name (| globals, locals_stack, "excess_blob_gas" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "max_gas_fee", + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_total_blob_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_blob_gas" |) + |) + |) in + let _ := M.assign_local (| + "blob_versioned_hashes" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "blob_versioned_hashes" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_versioned_hashes" , + make_tuple [ ] + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "sender" |); M.get_name (| globals, locals_stack, "effective_gas_price" |); M.get_name (| globals, locals_stack, "blob_versioned_hashes" |) ] + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "03", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "prev_randao"; "transactions"; "chain_id"; "withdrawals"; "parent_beacon_block_root"; "excess_blob_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "blob_gas_used" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "beacon_block_roots_contract_code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "BEACON_ROOTS_ADDRESS" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "system_tx_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "system_tx_env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "system_tx_output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "system_tx_message" |); + M.get_name (| globals, locals_stack, "system_tx_env" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_touched_empty_accounts" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "system_tx_env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "system_tx_output" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "map" |), + make_list [ + M.get_name (| globals, locals_stack, "decode_transaction" |); + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "encode_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |); M.get_name (| globals, locals_stack, "blob_versioned_hashes" |) ], + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "base_fee_per_gas" |); + M.get_name (| globals, locals_stack, "excess_blob_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "blob_gas_used", + M.call (| + M.get_name (| globals, locals_stack, "calculate_total_blob_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "blob_gas_used" |), + M.get_name (| globals, locals_stack, "MAX_BLOB_GAS_PER_BLOCK" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "wd" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "withdrawals" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "withdrawals_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "wd" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "process_withdrawal" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "wd" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "wd" |), "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "wd" |), "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "withdrawals_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "blob_gas_used" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_gas_fee" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_data_fee" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "excess_blob_gas" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_gas_fee" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "effective_gas_fee" |) + |), + M.get_name (| globals, locals_stack, "blob_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); M.get_name (| globals, locals_stack, "BlobTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_touched_empty_accounts" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); M.get_name (| globals, locals_stack, "BlobTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "_address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |), + M.get_name (| globals, locals_stack, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_4844" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_2930_in_globals : + IsInGlobals globals "signing_hash_2930" (make_function signing_hash_2930). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_1559_in_globals : + IsInGlobals globals "signing_hash_1559" (make_function signing_hash_1559). + +Definition signing_hash_4844 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "03", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_blob_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "blob_versioned_hashes" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_4844_in_globals : + IsInGlobals globals "signing_hash_4844" (make_function signing_hash_4844). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/fork_types.md new file mode 100644 index 00000000..3b2e8402 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/fork_types.md @@ -0,0 +1,113 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition VersionedHash : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/state.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/state.md new file mode 100644 index 00000000..78f577a0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/state.md @@ -0,0 +1,1646 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_cancun_blocks_imports_Withdrawal : + IsImported globals "ethereum.cancun.blocks" "Withdrawal". + +Axiom ethereum_cancun_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.cancun.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_cancun_fork_types_imports_Account : + IsImported globals "ethereum.cancun.fork_types" "Account". +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". + +Axiom ethereum_cancun_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.cancun.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_cancun_trie_imports_Trie : + IsImported globals "ethereum.cancun.trie" "Trie". +Axiom ethereum_cancun_trie_imports_copy_trie : + IsImported globals "ethereum.cancun.trie" "copy_trie". +Axiom ethereum_cancun_trie_imports_root : + IsImported globals "ethereum.cancun.trie" "root". +Axiom ethereum_cancun_trie_imports_trie_get : + IsImported globals "ethereum.cancun.trie" "trie_get". +Axiom ethereum_cancun_trie_imports_trie_set : + IsImported globals "ethereum.cancun.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition TransientStorage : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "created_accounts" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "transient_storage" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "transient_storage" |), "_snapshots" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: DictComp *)" + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "transient_storage" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + transient_storage : TransientStorage + The transient storage of the transaction. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "transient_storage" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "transient_storage" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "transient_storage" |), "_tries" |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "transient_storage" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom mark_account_created_in_globals : + IsInGlobals globals "mark_account_created" (make_function mark_account_created). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition process_withdrawal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "wd" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increase the balance of the withdrawing account. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "wd" |), "address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom process_withdrawal_in_globals : + IsInGlobals globals "process_withdrawal" (make_function process_withdrawal). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "_" |); M.get_name (| globals, locals_stack, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "original_account_trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "original_value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "original_value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_original_in_globals : + IsInGlobals globals "get_storage_original" (make_function get_storage_original). + +Definition get_transient_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "transient_storage"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "transient_storage" |), "_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_transient_storage_in_globals : + IsInGlobals globals "get_transient_storage" (make_function get_transient_storage). + +Definition set_transient_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "transient_storage"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "transient_storage" |), "_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "transient_storage" |), "_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "transient_storage" |), "_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_transient_storage_in_globals : + IsInGlobals globals "set_transient_storage" (make_function set_transient_storage). + +Definition destroy_touched_empty_accounts : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "touched_accounts" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_name (| globals, locals_stack, "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom destroy_touched_empty_accounts_in_globals : + IsInGlobals globals "destroy_touched_empty_accounts" (make_function destroy_touched_empty_accounts). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/transactions.md new file mode 100644 index 00000000..beb8baa9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/transactions.md @@ -0,0 +1,379 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_VersionedHash : + IsImported globals "ethereum.cancun.fork_types" "VersionedHash". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AccessListTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition FeeMarketTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BlobTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); M.get_name (| globals, locals_stack, "BlobTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "03", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_transaction_in_globals : + IsInGlobals globals "encode_transaction" (make_function encode_transaction). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 3 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "BlobTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom decode_transaction_in_globals : + IsInGlobals globals "decode_transaction" (make_function decode_transaction). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/trie.md new file mode 100644 index 00000000..eada1eb2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/trie.md @@ -0,0 +1,1654 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_shanghai_imports_trie : + IsImported globals "ethereum.shanghai" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_cancun_blocks_imports_Receipt : + IsImported globals "ethereum.cancun.blocks" "Receipt". +Axiom ethereum_cancun_blocks_imports_Withdrawal : + IsImported globals "ethereum.cancun.blocks" "Withdrawal". + +Axiom ethereum_cancun_fork_types_imports_Account : + IsImported globals "ethereum.cancun.fork_types" "Account". +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". +Axiom ethereum_cancun_fork_types_imports_encode_account : + IsImported globals "ethereum.cancun.fork_types" "encode_account". + +Axiom ethereum_cancun_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.cancun.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); M.get_name (| globals, locals_stack, "Withdrawal" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Withdrawal" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Withdrawal" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/__init__.md new file mode 100644 index 00000000..d0ceaaf9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/address.md new file mode 100644 index 00000000..6ac23b7c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this cancun version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/hexadecimal.md new file mode 100644 index 00000000..084f51fd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Cancun types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Bloom : + IsImported globals "ethereum.cancun.fork_types" "Bloom". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/message.md new file mode 100644 index 00000000..fdd8e02c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/utils/message.md @@ -0,0 +1,278 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Axiom ethereum_cancun_state_imports_get_account : + IsImported globals "ethereum.cancun.state" "get_account". + +Axiom ethereum_cancun_vm_imports_Environment : + IsImported globals "ethereum.cancun.vm" "Environment". +Axiom ethereum_cancun_vm_imports_Message : + IsImported globals "ethereum.cancun.vm" "Message". + +Axiom ethereum_cancun_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_cancun_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.cancun.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, locals_stack, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/__init__.md new file mode 100644 index 00000000..42e15314 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/__init__.md @@ -0,0 +1,277 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_VersionedHash : + IsImported globals "ethereum.cancun.fork_types" "VersionedHash". + +Axiom ethereum_cancun_state_imports_State : + IsImported globals "ethereum.cancun.state" "State". +Axiom ethereum_cancun_state_imports_TransientStorage : + IsImported globals "ethereum.cancun.state" "TransientStorage". +Axiom ethereum_cancun_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.cancun.state" "account_exists_and_is_empty". + +Axiom ethereum_cancun_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/exceptions.md new file mode 100644 index 00000000..ea0f49d9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/exceptions.md @@ -0,0 +1,191 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidParameter : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidContractPrefix : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition KZGProofError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/gas.md new file mode 100644 index 00000000..023ed53c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/gas.md @@ -0,0 +1,1257 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". +Axiom ethereum_utils_numeric_imports_taylor_exponential : + IsImported globals "ethereum.utils.numeric" "taylor_exponential". + +Axiom ethereum_cancun_blocks_imports_Header : + IsImported globals "ethereum.cancun.blocks" "Header". + +Axiom ethereum_cancun_transactions_imports_BlobTransaction : + IsImported globals "ethereum.cancun.transactions" "BlobTransaction". +Axiom ethereum_cancun_transactions_imports_Transaction : + IsImported globals "ethereum.cancun.transactions" "Transaction". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition GAS_INIT_CODE_WORD_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_BLOBHASH_OPCODE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_POINT_EVALUATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50000 + ], + make_dict [] + |) +)). + +Definition TARGET_BLOB_GAS_PER_BLOCK : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U64" |), + make_list [ + Constant.int 393216 + ], + make_dict [] + |) +)). + +Definition GAS_PER_BLOB : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.pow (| + Constant.int 2, + Constant.int 17 + |) + ], + make_dict [] + |) +)). + +Definition MIN_BLOB_GASPRICE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition BLOB_GASPRICE_UPDATE_FRACTION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3338477 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). + +Definition init_code_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "init_code_length" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.floor_div (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_INIT_CODE_WORD_COST" |), + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "init_code_length" |) + ], + make_dict [] + |) + |), + Constant.int 32 + |) + |) in + M.pure Constant.None_)). + +Axiom init_code_cost_in_globals : + IsInGlobals globals "init_code_cost" (make_function init_code_cost). + +Definition calculate_excess_blob_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "parent_blob_gas" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "excess_blob_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "blob_gas_used" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "parent_blob_gas" |), + M.get_name (| globals, locals_stack, "TARGET_BLOB_GAS_PER_BLOCK" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U64" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_blob_gas" |), + M.get_name (| globals, locals_stack, "TARGET_BLOB_GAS_PER_BLOCK" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom calculate_excess_blob_gas_in_globals : + IsInGlobals globals "calculate_excess_blob_gas" (make_function calculate_excess_blob_gas). + +Definition calculate_total_blob_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_PER_BLOB" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "blob_versioned_hashes" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom calculate_total_blob_gas_in_globals : + IsInGlobals globals "calculate_total_blob_gas" (make_function calculate_total_blob_gas). + +Definition calculate_blob_gas_price : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "excess_blob_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "taylor_exponential" |), + make_list [ + M.get_name (| globals, locals_stack, "MIN_BLOB_GASPRICE" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "excess_blob_gas" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "BLOB_GASPRICE_UPDATE_FRACTION" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_blob_gas_price_in_globals : + IsInGlobals globals "calculate_blob_gas_price" (make_function calculate_blob_gas_price). + +Definition calculate_data_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "excess_blob_gas"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_total_blob_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_blob_gas_price" |), + make_list [ + M.get_name (| globals, locals_stack, "excess_blob_gas" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_data_fee_in_globals : + IsInGlobals globals "calculate_data_fee" (make_function calculate_data_fee). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/__init__.md new file mode 100644 index 00000000..f7e690a1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_cancun_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.cancun.vm.instructions" "arithmetic". + +Axiom ethereum_cancun_vm_instructions_imports_bitwise : + IsImported globals "ethereum.cancun.vm.instructions" "bitwise". + +Axiom ethereum_cancun_vm_instructions_imports_block : + IsImported globals "ethereum.cancun.vm.instructions" "block". + +Axiom ethereum_cancun_vm_instructions_imports_comparison : + IsImported globals "ethereum.cancun.vm.instructions" "comparison". + +Axiom ethereum_cancun_vm_instructions_imports_control_flow : + IsImported globals "ethereum.cancun.vm.instructions" "control_flow". + +Axiom ethereum_cancun_vm_instructions_imports_environment : + IsImported globals "ethereum.cancun.vm.instructions" "environment". + +Axiom ethereum_cancun_vm_instructions_imports_keccak : + IsImported globals "ethereum.cancun.vm.instructions" "keccak". + +Axiom ethereum_cancun_vm_instructions_imports_log : + IsImported globals "ethereum.cancun.vm.instructions" "log". + +Axiom ethereum_cancun_vm_instructions_imports_memory : + IsImported globals "ethereum.cancun.vm.instructions" "memory". + +Axiom ethereum_cancun_vm_instructions_imports_stack : + IsImported globals "ethereum.cancun.vm.instructions" "stack". + +Axiom ethereum_cancun_vm_instructions_imports_storage : + IsImported globals "ethereum.cancun.vm.instructions" "storage". + +Axiom ethereum_cancun_vm_instructions_imports_system : + IsImported globals "ethereum.cancun.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/arithmetic.md new file mode 100644 index 00000000..5b34813a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.cancun.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_cancun_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_cancun_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_LOW". +Axiom ethereum_cancun_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.cancun.vm.gas" "GAS_MID". +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/bitwise.md new file mode 100644 index 00000000..80dea90d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/block.md new file mode 100644 index 00000000..8e6d0291 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/block.md @@ -0,0 +1,468 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition prev_randao : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "prev_randao" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom prev_randao_in_globals : + IsInGlobals globals "prev_randao" (make_function prev_randao). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom chain_id_in_globals : + IsInGlobals globals "chain_id" (make_function chain_id). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/comparison.md new file mode 100644 index 00000000..1582532c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/control_flow.md new file mode 100644 index 00000000..ce7e1a19 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.cancun.vm.gas" "GAS_HIGH". +Axiom ethereum_cancun_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.cancun.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_cancun_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.cancun.vm.gas" "GAS_MID". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.cancun.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/environment.md new file mode 100644 index 00000000..c105006a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/environment.md @@ -0,0 +1,1767 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.cancun.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_cancun_state_imports_get_account : + IsImported globals "ethereum.cancun.state" "get_account". + +Axiom ethereum_cancun_utils_address_imports_to_address : + IsImported globals "ethereum.cancun.utils.address" "to_address". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". +Axiom ethereum_cancun_vm_memory_imports_memory_write : + IsImported globals "ethereum.cancun.vm.memory" "memory_write". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_BLOBHASH_OPCODE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BLOBHASH_OPCODE". +Axiom ethereum_cancun_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COPY". +Axiom ethereum_cancun_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.cancun.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_cancun_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.cancun.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_calculate_blob_gas_price : + IsImported globals "ethereum.cancun.vm.gas" "calculate_blob_gas_price". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom self_balance_in_globals : + IsInGlobals globals "self_balance" (make_function self_balance). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom base_fee_in_globals : + IsInGlobals globals "base_fee" (make_function base_fee). + +Definition blob_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the versioned hash at a particular index on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOBHASH_OPCODE" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "index" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "blob_versioned_hashes" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "blob_versioned_hashes" |), + M.get_name (| globals, locals_stack, "index" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes32" |), + make_list [ + BinOp.mult (| + Constant.bytes "00", + Constant.int 32 + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "blob_hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom blob_hash_in_globals : + IsInGlobals globals "blob_hash" (make_function blob_hash). + +Definition blob_base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the blob base fee on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blob_base_fee" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_blob_gas_price" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "excess_blob_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "blob_base_fee" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom blob_base_fee_in_globals : + IsInGlobals globals "blob_base_fee" (make_function blob_base_fee). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/keccak.md new file mode 100644 index 00000000..82ad2bcc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.cancun.vm.gas" "GAS_KECCAK256". +Axiom ethereum_cancun_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.cancun.vm.memory" "memory_read_bytes". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/log.md new file mode 100644 index 00000000..3b665d1a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.cancun.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_cancun_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.cancun.vm.gas" "GAS_LOG". +Axiom ethereum_cancun_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.cancun.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_cancun_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.cancun.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.cancun.vm.memory" "memory_read_bytes". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/memory.md new file mode 100644 index 00000000..ca2c459b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/memory.md @@ -0,0 +1,560 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COPY". +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.cancun.vm.memory" "memory_read_bytes". +Axiom ethereum_cancun_vm_memory_imports_memory_write : + IsImported globals "ethereum.cancun.vm.memory" "memory_write". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). + +Definition mcopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy the bytes in memory from one location to another. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "destination" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "source" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "length" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "length" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "source" |); M.get_name (| globals, locals_stack, "length" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "destination" |); M.get_name (| globals, locals_stack, "length" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "source" |); + M.get_name (| globals, locals_stack, "length" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "destination" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mcopy_in_globals : + IsInGlobals globals "mcopy" (make_function mcopy). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/stack.md new file mode 100644 index 00000000..f27e4066 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/stack.md @@ -0,0 +1,1008 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". +Axiom ethereum_cancun_vm_imports_stack : + IsImported globals "ethereum.cancun.vm" "stack". + +Axiom ethereum_cancun_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.cancun.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "num_bytes" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/storage.md new file mode 100644 index 00000000..cb041b4f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/storage.md @@ -0,0 +1,655 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_state_imports_get_storage : + IsImported globals "ethereum.cancun.state" "get_storage". +Axiom ethereum_cancun_state_imports_get_storage_original : + IsImported globals "ethereum.cancun.state" "get_storage_original". +Axiom ethereum_cancun_state_imports_get_transient_storage : + IsImported globals "ethereum.cancun.state" "get_transient_storage". +Axiom ethereum_cancun_state_imports_set_storage : + IsImported globals "ethereum.cancun.state" "set_storage". +Axiom ethereum_cancun_state_imports_set_transient_storage : + IsImported globals "ethereum.cancun.state" "set_transient_storage". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". +Axiom ethereum_cancun_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.cancun.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_cancun_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.cancun.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_cancun_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_cancun_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.cancun.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_cancun_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.cancun.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_cancun_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_cancun_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). + +Definition tload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_transient_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "transient_storage" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom tload_in_globals : + IsInGlobals globals "tload" (make_function tload). + +Definition tstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's transient storage. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_transient_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "transient_storage" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom tstore_in_globals : + IsInGlobals globals "tstore" (make_function tstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/system.md new file mode 100644 index 00000000..81f083da --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/instructions/system.md @@ -0,0 +1,2347 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Axiom ethereum_cancun_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.cancun.state" "account_exists_and_is_empty". +Axiom ethereum_cancun_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.cancun.state" "account_has_code_or_nonce". +Axiom ethereum_cancun_state_imports_get_account : + IsImported globals "ethereum.cancun.state" "get_account". +Axiom ethereum_cancun_state_imports_increment_nonce : + IsImported globals "ethereum.cancun.state" "increment_nonce". +Axiom ethereum_cancun_state_imports_is_account_alive : + IsImported globals "ethereum.cancun.state" "is_account_alive". +Axiom ethereum_cancun_state_imports_move_ether : + IsImported globals "ethereum.cancun.state" "move_ether". +Axiom ethereum_cancun_state_imports_set_account_balance : + IsImported globals "ethereum.cancun.state" "set_account_balance". + +Axiom ethereum_cancun_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.cancun.utils.address" "compute_contract_address". +Axiom ethereum_cancun_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.cancun.utils.address" "compute_create2_contract_address". +Axiom ethereum_cancun_utils_address_imports_to_address : + IsImported globals "ethereum.cancun.utils.address" "to_address". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". +Axiom ethereum_cancun_vm_imports_Message : + IsImported globals "ethereum.cancun.vm" "Message". +Axiom ethereum_cancun_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.cancun.vm" "incorporate_child_on_error". +Axiom ethereum_cancun_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.cancun.vm" "incorporate_child_on_success". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". +Axiom ethereum_cancun_vm_exceptions_imports_Revert : + IsImported globals "ethereum.cancun.vm.exceptions" "Revert". +Axiom ethereum_cancun_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.cancun.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_cancun_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_cancun_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_CREATE". +Axiom ethereum_cancun_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_cancun_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.cancun.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_cancun_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.cancun.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_cancun_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.cancun.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_cancun_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.cancun.vm.gas" "GAS_ZERO". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.cancun.vm.gas" "calculate_message_call_gas". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". +Axiom ethereum_cancun_vm_gas_imports_init_code_cost : + IsImported globals "ethereum.cancun.vm.gas" "init_code_cost". +Axiom ethereum_cancun_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.cancun.vm.gas" "max_message_call_gas". + +Axiom ethereum_cancun_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.cancun.vm.memory" "memory_read_bytes". +Axiom ethereum_cancun_vm_memory_imports_memory_write : + IsImported globals "ethereum.cancun.vm.memory" "memory_write". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size"; "init_code_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |), + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "MAX_CODE_SIZE" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "init_code_gas" , + M.call (| + M.get_name (| globals, locals_stack, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |), + M.get_name (| globals, locals_stack, "init_code_gas" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |); + M.get_name (| globals, locals_stack, "init_code_gas" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "init_code_gas" , + M.call (| + M.get_name (| globals, locals_stack, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |), + M.get_name (| globals, locals_stack, "init_code_gas" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |); + M.get_name (| globals, locals_stack, "init_code_gas" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "beneficiary" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + M.get_name (| globals, locals_stack, "originator_balance" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_field (| M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |), "created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/interpreter.md new file mode 100644 index 00000000..bf911225 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/interpreter.md @@ -0,0 +1,702 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Axiom ethereum_cancun_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.cancun.state" "account_exists_and_is_empty". +Axiom ethereum_cancun_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.cancun.state" "account_has_code_or_nonce". +Axiom ethereum_cancun_state_imports_begin_transaction : + IsImported globals "ethereum.cancun.state" "begin_transaction". +Axiom ethereum_cancun_state_imports_commit_transaction : + IsImported globals "ethereum.cancun.state" "commit_transaction". +Axiom ethereum_cancun_state_imports_destroy_storage : + IsImported globals "ethereum.cancun.state" "destroy_storage". +Axiom ethereum_cancun_state_imports_increment_nonce : + IsImported globals "ethereum.cancun.state" "increment_nonce". +Axiom ethereum_cancun_state_imports_mark_account_created : + IsImported globals "ethereum.cancun.state" "mark_account_created". +Axiom ethereum_cancun_state_imports_move_ether : + IsImported globals "ethereum.cancun.state" "move_ether". +Axiom ethereum_cancun_state_imports_rollback_transaction : + IsImported globals "ethereum.cancun.state" "rollback_transaction". +Axiom ethereum_cancun_state_imports_set_code : + IsImported globals "ethereum.cancun.state" "set_code". +Axiom ethereum_cancun_state_imports_touch_account : + IsImported globals "ethereum.cancun.state" "touch_account". + +Axiom ethereum_cancun_vm_imports_Message : + IsImported globals "ethereum.cancun.vm" "Message". + +Axiom ethereum_cancun_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.cancun.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_cancun_vm_imports_Environment : + IsImported globals "ethereum.cancun.vm" "Environment". +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.cancun.vm.exceptions" "AddressCollision". +Axiom ethereum_cancun_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.cancun.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_cancun_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.cancun.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_cancun_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.cancun.vm.exceptions" "InvalidOpcode". +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". +Axiom ethereum_cancun_vm_exceptions_imports_Revert : + IsImported globals "ethereum.cancun.vm.exceptions" "Revert". +Axiom ethereum_cancun_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.cancun.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_cancun_vm_instructions_imports_Ops : + IsImported globals "ethereum.cancun.vm.instructions" "Ops". +Axiom ethereum_cancun_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.cancun.vm.instructions" "op_implementation". + +Axiom ethereum_cancun_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.cancun.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/memory.md new file mode 100644 index 00000000..3c38dedb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..a2e72553 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/__init__.md @@ -0,0 +1,134 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_cancun_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.cancun.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS"; Constant.str "POINT_EVALUATION_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). + +Definition POINT_EVALUATION_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x0a" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..5b94405e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..dca14dc3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,144 @@ +# ๐Ÿ“ blake2f.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/blake2f.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.blake2f". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.cancun.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, locals_stack, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, locals_stack, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, locals_stack, "rounds" |); + M.get_name (| globals, locals_stack, "h" |); + M.get_name (| globals, locals_stack, "m" |); + M.get_name (| globals, locals_stack, "t_0" |); + M.get_name (| globals, locals_stack, "t_1" |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom blake2f_in_globals : + IsInGlobals globals "blake2f" (make_function blake2f). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..9560367c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.cancun.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..ce138bed --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.cancun.vm.gas" "GAS_IDENTITY". +Axiom ethereum_cancun_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..be6f6fff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/mapping.md @@ -0,0 +1,85 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Axiom ethereum_cancun_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_POINT_EVALUATION_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "POINT_EVALUATION_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_cancun_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_cancun_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_cancun_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_cancun_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_cancun_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_cancun_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_cancun_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_cancun_vm_precompiled_contracts_point_evaluation_imports_point_evaluation : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.point_evaluation" "point_evaluation". + +Axiom ethereum_cancun_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_cancun_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..07a05d87 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/modexp.md @@ -0,0 +1,700 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |); + M.get_name (| globals, locals_stack, "exp_length" |); + M.get_name (| globals, locals_stack, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Axiom complexity_in_globals : + IsInGlobals globals "complexity" (make_function complexity). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, locals_stack, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, locals_stack, "length_part" |), + M.get_name (| globals, locals_stack, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "count" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom iterations_in_globals : + IsInGlobals globals "iterations" (make_function iterations). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, locals_stack, "complexity" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, locals_stack, "iterations" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |); + M.get_name (| globals, locals_stack, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "multiplication_complexity" |), + M.get_name (| globals, locals_stack, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom gas_cost_in_globals : + IsInGlobals globals "gas_cost" (make_function gas_cost). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/point_evaluation.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/point_evaluation.md new file mode 100644 index 00000000..85e9ddc3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/point_evaluation.md @@ -0,0 +1,231 @@ +# ๐Ÿ“ point_evaluation.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.point_evaluation". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) POINT EVALUATION PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the POINT EVALUATION precompiled contract. +". + +Axiom eth2spec_deneb_mainnet_imports_KZGCommitment : + IsImported globals "eth2spec.deneb.mainnet" "KZGCommitment". +Axiom eth2spec_deneb_mainnet_imports_kzg_commitment_to_versioned_hash : + IsImported globals "eth2spec.deneb.mainnet" "kzg_commitment_to_versioned_hash". +Axiom eth2spec_deneb_mainnet_imports_verify_kzg_proof : + IsImported globals "eth2spec.deneb.mainnet" "verify_kzg_proof". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_KZGProofError : + IsImported globals "ethereum.cancun.vm.exceptions" "KZGProofError". + +Axiom ethereum_cancun_vm_gas_imports_GAS_POINT_EVALUATION : + IsImported globals "ethereum.cancun.vm.gas" "GAS_POINT_EVALUATION". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Definition FIELD_ELEMENTS_PER_BLOB : Value.t := M.run ltac:(M.monadic ( + Constant.int 4096 +)). + +Definition BLS_MODULUS : Value.t := M.run ltac:(M.monadic ( + Constant.int 52435875175126190479447740508185965837690552500527637822603658699938581184513 +)). + +Definition VERSIONED_HASH_VERSION_KZG : Value.t := M.run ltac:(M.monadic ( + Constant.bytes "01" +)). + +Definition point_evaluation : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "KZGProofError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "versioned_hash" , + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + Constant.None_, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "z" , + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + Constant.int 32, + Constant.int 64, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "y" , + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + Constant.int 64, + Constant.int 96, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "commitment" , + M.call (| + M.get_name (| globals, locals_stack, "KZGCommitment" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + Constant.int 96, + Constant.int 144, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "proof" , + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + Constant.int 144, + Constant.int 192, + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_POINT_EVALUATION" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "kzg_commitment_to_versioned_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "commitment" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "versioned_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "KZGProofError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_name (| globals, locals_stack, "kzg_proof_verification" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "KZGProofError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "FIELD_ELEMENTS_PER_BLOB" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "BLS_MODULUS" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom point_evaluation_in_globals : + IsInGlobals globals "point_evaluation" (make_function point_evaluation). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..7dfa66a9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.cancun.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_cancun_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..b0c965cf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.cancun.vm.gas" "GAS_SHA256". +Axiom ethereum_cancun_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/runtime.md new file mode 100644 index 00000000..40ad871f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_vm_instructions_imports_Ops : + IsImported globals "ethereum.cancun.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/stack.md new file mode 100644 index 00000000..53ae0ba9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/cancun/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/cancun/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.cancun.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_cancun_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.cancun.vm.exceptions" "StackOverflowError". +Axiom ethereum_cancun_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.cancun.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/__init__.md new file mode 100644 index 00000000..3feaf8ee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/__init__.md @@ -0,0 +1,31 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 7280000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/blocks.md new file mode 100644 index 00000000..e90f92df --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/blocks.md @@ -0,0 +1,91 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Bloom : + IsImported globals "ethereum.constantinople.fork_types" "Bloom". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". + +Axiom ethereum_constantinople_transactions_imports_Transaction : + IsImported globals "ethereum.constantinople.transactions" "Transaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/bloom.md new file mode 100644 index 00000000..1c512226 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". + +Axiom ethereum_constantinople_fork_types_imports_Bloom : + IsImported globals "ethereum.constantinople.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/fork.md new file mode 100644 index 00000000..16d03ac5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/fork.md @@ -0,0 +1,2862 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_imports_vm : + IsImported globals "ethereum.constantinople" "vm". + +Axiom ethereum_constantinople_blocks_imports_Block : + IsImported globals "ethereum.constantinople.blocks" "Block". +Axiom ethereum_constantinople_blocks_imports_Header : + IsImported globals "ethereum.constantinople.blocks" "Header". +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". +Axiom ethereum_constantinople_blocks_imports_Receipt : + IsImported globals "ethereum.constantinople.blocks" "Receipt". + +Axiom ethereum_constantinople_bloom_imports_logs_bloom : + IsImported globals "ethereum.constantinople.bloom" "logs_bloom". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Bloom : + IsImported globals "ethereum.constantinople.fork_types" "Bloom". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". + +Axiom ethereum_constantinople_state_imports_State : + IsImported globals "ethereum.constantinople.state" "State". +Axiom ethereum_constantinople_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.constantinople.state" "account_exists_and_is_empty". +Axiom ethereum_constantinople_state_imports_create_ether : + IsImported globals "ethereum.constantinople.state" "create_ether". +Axiom ethereum_constantinople_state_imports_destroy_account : + IsImported globals "ethereum.constantinople.state" "destroy_account". +Axiom ethereum_constantinople_state_imports_get_account : + IsImported globals "ethereum.constantinople.state" "get_account". +Axiom ethereum_constantinople_state_imports_increment_nonce : + IsImported globals "ethereum.constantinople.state" "increment_nonce". +Axiom ethereum_constantinople_state_imports_set_account_balance : + IsImported globals "ethereum.constantinople.state" "set_account_balance". +Axiom ethereum_constantinople_state_imports_state_root : + IsImported globals "ethereum.constantinople.state" "state_root". + +Axiom ethereum_constantinople_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.constantinople.transactions" "TX_BASE_COST". +Axiom ethereum_constantinople_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.constantinople.transactions" "TX_CREATE_COST". +Axiom ethereum_constantinople_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.constantinople.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_constantinople_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.constantinople.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_constantinople_transactions_imports_Transaction : + IsImported globals "ethereum.constantinople.transactions" "Transaction". + +Axiom ethereum_constantinople_trie_imports_Trie : + IsImported globals "ethereum.constantinople.trie" "Trie". +Axiom ethereum_constantinople_trie_imports_root : + IsImported globals "ethereum.constantinople.trie" "root". +Axiom ethereum_constantinople_trie_imports_trie_set : + IsImported globals "ethereum.constantinople.trie" "trie_set". + +Axiom ethereum_constantinople_utils_message_imports_prepare_message : + IsImported globals "ethereum.constantinople.utils.message" "prepare_message". + +Axiom ethereum_constantinople_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.constantinople.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |); + M.get_name (| globals, locals_stack, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "v" |); M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/fork_types.md new file mode 100644 index 00000000..926a075c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/state.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/state.md new file mode 100644 index 00000000..b9ad0e87 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/state.md @@ -0,0 +1,1215 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_constantinople_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.constantinople.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_constantinople_fork_types_imports_Account : + IsImported globals "ethereum.constantinople.fork_types" "Account". +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". + +Axiom ethereum_constantinople_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.constantinople.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_constantinople_trie_imports_Trie : + IsImported globals "ethereum.constantinople.trie" "Trie". +Axiom ethereum_constantinople_trie_imports_copy_trie : + IsImported globals "ethereum.constantinople.trie" "copy_trie". +Axiom ethereum_constantinople_trie_imports_root : + IsImported globals "ethereum.constantinople.trie" "root". +Axiom ethereum_constantinople_trie_imports_trie_get : + IsImported globals "ethereum.constantinople.trie" "trie_get". +Axiom ethereum_constantinople_trie_imports_trie_set : + IsImported globals "ethereum.constantinople.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/transactions.md new file mode 100644 index 00000000..49708aa8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/transactions.md @@ -0,0 +1,63 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/trie.md new file mode 100644 index 00000000..ba48f59d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/trie.md @@ -0,0 +1,1639 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_byzantium_imports_trie : + IsImported globals "ethereum.byzantium" "trie". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_constantinople_blocks_imports_Receipt : + IsImported globals "ethereum.constantinople.blocks" "Receipt". + +Axiom ethereum_constantinople_fork_types_imports_Account : + IsImported globals "ethereum.constantinople.fork_types" "Account". +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". +Axiom ethereum_constantinople_fork_types_imports_encode_account : + IsImported globals "ethereum.constantinople.fork_types" "encode_account". + +Axiom ethereum_constantinople_transactions_imports_Transaction : + IsImported globals "ethereum.constantinople.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Receipt" |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/__init__.md new file mode 100644 index 00000000..7c828b02 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/address.md new file mode 100644 index 00000000..ae51d991 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this constantinople version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/hexadecimal.md new file mode 100644 index 00000000..2e5f3ccc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Constantinople types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Bloom : + IsImported globals "ethereum.constantinople.fork_types" "Bloom". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/message.md new file mode 100644 index 00000000..25cb284e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/utils/message.md @@ -0,0 +1,224 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_state_imports_get_account : + IsImported globals "ethereum.constantinople.state" "get_account". + +Axiom ethereum_constantinople_vm_imports_Environment : + IsImported globals "ethereum.constantinople.vm" "Environment". +Axiom ethereum_constantinople_vm_imports_Message : + IsImported globals "ethereum.constantinople.vm" "Message". + +Axiom ethereum_constantinople_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.constantinople.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/__init__.md new file mode 100644 index 00000000..18f4f11a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/__init__.md @@ -0,0 +1,255 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_state_imports_State : + IsImported globals "ethereum.constantinople.state" "State". +Axiom ethereum_constantinople_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.constantinople.state" "account_exists_and_is_empty". + +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/exceptions.md new file mode 100644 index 00000000..f08899a6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/exceptions.md @@ -0,0 +1,161 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/gas.md new file mode 100644 index 00000000..542ab2cd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/gas.md @@ -0,0 +1,948 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.constantinople.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/__init__.md new file mode 100644 index 00000000..f5e24e2d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_constantinople_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.constantinople.vm.instructions" "arithmetic". + +Axiom ethereum_constantinople_vm_instructions_imports_bitwise : + IsImported globals "ethereum.constantinople.vm.instructions" "bitwise". + +Axiom ethereum_constantinople_vm_instructions_imports_block : + IsImported globals "ethereum.constantinople.vm.instructions" "block". + +Axiom ethereum_constantinople_vm_instructions_imports_comparison : + IsImported globals "ethereum.constantinople.vm.instructions" "comparison". + +Axiom ethereum_constantinople_vm_instructions_imports_control_flow : + IsImported globals "ethereum.constantinople.vm.instructions" "control_flow". + +Axiom ethereum_constantinople_vm_instructions_imports_environment : + IsImported globals "ethereum.constantinople.vm.instructions" "environment". + +Axiom ethereum_constantinople_vm_instructions_imports_keccak : + IsImported globals "ethereum.constantinople.vm.instructions" "keccak". + +Axiom ethereum_constantinople_vm_instructions_imports_log : + IsImported globals "ethereum.constantinople.vm.instructions" "log". + +Axiom ethereum_constantinople_vm_instructions_imports_memory : + IsImported globals "ethereum.constantinople.vm.instructions" "memory". + +Axiom ethereum_constantinople_vm_instructions_imports_stack : + IsImported globals "ethereum.constantinople.vm.instructions" "stack". + +Axiom ethereum_constantinople_vm_instructions_imports_storage : + IsImported globals "ethereum.constantinople.vm.instructions" "storage". + +Axiom ethereum_constantinople_vm_instructions_imports_system : + IsImported globals "ethereum.constantinople.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/arithmetic.md new file mode 100644 index 00000000..24961b05 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_constantinople_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_LOW". +Axiom ethereum_constantinople_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_MID". +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/bitwise.md new file mode 100644 index 00000000..d1d3c951 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/block.md new file mode 100644 index 00000000..0988c8e3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/block.md @@ -0,0 +1,380 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/comparison.md new file mode 100644 index 00000000..338b5b91 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/control_flow.md new file mode 100644 index 00000000..554d30c4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_HIGH". +Axiom ethereum_constantinople_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_constantinople_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_MID". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.constantinople.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/environment.md new file mode 100644 index 00000000..05390905 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/environment.md @@ -0,0 +1,1391 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.constantinople.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_constantinople_state_imports_get_account : + IsImported globals "ethereum.constantinople.state" "get_account". + +Axiom ethereum_constantinople_utils_address_imports_to_address : + IsImported globals "ethereum.constantinople.utils.address" "to_address". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". +Axiom ethereum_constantinople_vm_memory_imports_memory_write : + IsImported globals "ethereum.constantinople.vm.memory" "memory_write". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.constantinople.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BALANCE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_CODE_HASH : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CODE_HASH". +Axiom ethereum_constantinople_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_COPY". +Axiom ethereum_constantinople_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_constantinople_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_CODE_HASH" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/keccak.md new file mode 100644 index 00000000..8f2100db --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_KECCAK256". +Axiom ethereum_constantinople_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.constantinople.vm.memory" "memory_read_bytes". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/log.md new file mode 100644 index 00000000..f4664c63 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.constantinople.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_LOG". +Axiom ethereum_constantinople_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_constantinople_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.constantinople.vm.memory" "memory_read_bytes". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/memory.md new file mode 100644 index 00000000..048d692d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.constantinople.vm.memory" "memory_read_bytes". +Axiom ethereum_constantinople_vm_memory_imports_memory_write : + IsImported globals "ethereum.constantinople.vm.memory" "memory_write". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/stack.md new file mode 100644 index 00000000..ae8cbee6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". +Axiom ethereum_constantinople_vm_imports_stack : + IsImported globals "ethereum.constantinople.vm" "stack". + +Axiom ethereum_constantinople_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.constantinople.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/storage.md new file mode 100644 index 00000000..dfefd5c2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/storage.md @@ -0,0 +1,265 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_constantinople_state_imports_get_storage : + IsImported globals "ethereum.constantinople.state" "get_storage". +Axiom ethereum_constantinople_state_imports_set_storage : + IsImported globals "ethereum.constantinople.state" "set_storage". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.constantinople.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SLOAD". +Axiom ethereum_constantinople_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_constantinople_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_constantinople_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/system.md new file mode 100644 index 00000000..641ef1e6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/instructions/system.md @@ -0,0 +1,2178 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.constantinople.state" "account_exists_and_is_empty". +Axiom ethereum_constantinople_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.constantinople.state" "account_has_code_or_nonce". +Axiom ethereum_constantinople_state_imports_get_account : + IsImported globals "ethereum.constantinople.state" "get_account". +Axiom ethereum_constantinople_state_imports_increment_nonce : + IsImported globals "ethereum.constantinople.state" "increment_nonce". +Axiom ethereum_constantinople_state_imports_is_account_alive : + IsImported globals "ethereum.constantinople.state" "is_account_alive". +Axiom ethereum_constantinople_state_imports_set_account_balance : + IsImported globals "ethereum.constantinople.state" "set_account_balance". + +Axiom ethereum_constantinople_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.constantinople.utils.address" "compute_contract_address". +Axiom ethereum_constantinople_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.constantinople.utils.address" "compute_create2_contract_address". +Axiom ethereum_constantinople_utils_address_imports_to_address : + IsImported globals "ethereum.constantinople.utils.address" "to_address". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". +Axiom ethereum_constantinople_vm_imports_Message : + IsImported globals "ethereum.constantinople.vm" "Message". +Axiom ethereum_constantinople_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.constantinople.vm" "incorporate_child_on_error". +Axiom ethereum_constantinople_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.constantinople.vm" "incorporate_child_on_success". + +Axiom ethereum_constantinople_vm_exceptions_imports_Revert : + IsImported globals "ethereum.constantinople.vm.exceptions" "Revert". +Axiom ethereum_constantinople_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.constantinople.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CALL". +Axiom ethereum_constantinople_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CREATE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_constantinople_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_constantinople_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_constantinople_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_constantinople_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_ZERO". +Axiom ethereum_constantinople_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.constantinople.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_message_call_gas". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". +Axiom ethereum_constantinople_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.constantinople.vm.gas" "max_message_call_gas". + +Axiom ethereum_constantinople_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.constantinople.vm.memory" "memory_read_bytes". +Axiom ethereum_constantinople_vm_memory_imports_memory_write : + IsImported globals "ethereum.constantinople.vm.memory" "memory_write". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/interpreter.md new file mode 100644 index 00000000..104168ee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/interpreter.md @@ -0,0 +1,677 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.constantinople.state" "account_exists_and_is_empty". +Axiom ethereum_constantinople_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.constantinople.state" "account_has_code_or_nonce". +Axiom ethereum_constantinople_state_imports_begin_transaction : + IsImported globals "ethereum.constantinople.state" "begin_transaction". +Axiom ethereum_constantinople_state_imports_commit_transaction : + IsImported globals "ethereum.constantinople.state" "commit_transaction". +Axiom ethereum_constantinople_state_imports_destroy_storage : + IsImported globals "ethereum.constantinople.state" "destroy_storage". +Axiom ethereum_constantinople_state_imports_increment_nonce : + IsImported globals "ethereum.constantinople.state" "increment_nonce". +Axiom ethereum_constantinople_state_imports_move_ether : + IsImported globals "ethereum.constantinople.state" "move_ether". +Axiom ethereum_constantinople_state_imports_rollback_transaction : + IsImported globals "ethereum.constantinople.state" "rollback_transaction". +Axiom ethereum_constantinople_state_imports_set_code : + IsImported globals "ethereum.constantinople.state" "set_code". +Axiom ethereum_constantinople_state_imports_touch_account : + IsImported globals "ethereum.constantinople.state" "touch_account". + +Axiom ethereum_constantinople_vm_imports_Message : + IsImported globals "ethereum.constantinople.vm" "Message". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_constantinople_vm_imports_Environment : + IsImported globals "ethereum.constantinople.vm" "Environment". +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.constantinople.vm.exceptions" "AddressCollision". +Axiom ethereum_constantinople_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.constantinople.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_constantinople_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.constantinople.vm.exceptions" "InvalidOpcode". +Axiom ethereum_constantinople_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.constantinople.vm.exceptions" "OutOfGasError". +Axiom ethereum_constantinople_vm_exceptions_imports_Revert : + IsImported globals "ethereum.constantinople.vm.exceptions" "Revert". +Axiom ethereum_constantinople_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.constantinople.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_constantinople_vm_instructions_imports_Ops : + IsImported globals "ethereum.constantinople.vm.instructions" "Ops". +Axiom ethereum_constantinople_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.constantinople.vm.instructions" "op_implementation". + +Axiom ethereum_constantinople_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.constantinople.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/memory.md new file mode 100644 index 00000000..34a89716 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..bb54799c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/__init__.md @@ -0,0 +1,114 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_constantinople_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.constantinople.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..86318df1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". + +Axiom ethereum_constantinople_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.constantinople.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 500 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 40000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 80000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 100000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..414031a6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..468f1f65 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_IDENTITY". +Axiom ethereum_constantinople_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..5da07ca9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/mapping.md @@ -0,0 +1,75 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_constantinople_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_constantinople_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_constantinople_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_constantinople_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_constantinople_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_constantinople_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_constantinople_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_constantinople_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..c2d221d9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/modexp.md @@ -0,0 +1,560 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "exp_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.floor_div (| + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_mult_complexity" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "adjusted_exp_length" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition get_mult_complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Estimate the complexity of performing Karatsuba multiplication. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 64 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |), + Constant.int 4 + |), + BinOp.mult (| + Constant.int 96, + M.get_name (| globals, locals_stack, "x" |) + |) + |), + Constant.int 3072 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |), + Constant.int 16 + |), + BinOp.mult (| + Constant.int 480, + M.get_name (| globals, locals_stack, "x" |) + |) + |), + Constant.int 199680 + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_mult_complexity_in_globals : + IsInGlobals globals "get_mult_complexity" (make_function get_mult_complexity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..233c59fe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_constantinople_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..c4572593 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SHA256". +Axiom ethereum_constantinople_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/runtime.md new file mode 100644 index 00000000..1536dab3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_vm_instructions_imports_Ops : + IsImported globals "ethereum.constantinople.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/stack.md new file mode 100644 index 00000000..a2c3f4d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/constantinople/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/constantinople/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.constantinople.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_constantinople_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.constantinople.vm.exceptions" "StackOverflowError". +Axiom ethereum_constantinople_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.constantinople.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/crypto/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/crypto/__init__.md new file mode 100644 index 00000000..7dacee91 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/crypto/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/crypto/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.crypto.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Cryptographic primitives used in Ethereum. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/crypto/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/crypto/alt_bn128.md new file mode 100644 index 00000000..f4fbac9f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/crypto/alt_bn128.md @@ -0,0 +1,821 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/crypto/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.crypto.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +The alt_bn128 curve +^^^^^^^^^^^^^^^^^^^ +". + +Axiom ethereum_crypto_imports_elliptic_curve : + IsImported globals "ethereum.crypto" "elliptic_curve". +Axiom ethereum_crypto_imports_finite_field : + IsImported globals "ethereum.crypto" "finite_field". + +Definition ALT_BN128_PRIME : Value.t := M.run ltac:(M.monadic ( + Constant.int 21888242871839275222246405745257275088696311157297823662689037894645226208583 +)). + +Definition ALT_BN128_CURVE_ORDER : Value.t := M.run ltac:(M.monadic ( + Constant.int 21888242871839275222246405745257275088548364400416034343698204186575808495617 +)). + +Definition ATE_PAIRING_COUNT : Value.t := M.run ltac:(M.monadic ( + Constant.int 29793968203157093289 +)). + +Definition ATE_PAIRING_COUNT_BITS : Value.t := M.run ltac:(M.monadic ( + Constant.int 63 +)). + +Definition BNF : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BNP : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BNF2 : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_45 : Value.t := + Constant.str "autoapi_noindex". + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_48 : Value.t := + Constant.str "autoapi_noindex". + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_51 : Value.t := + Constant.str "autoapi_noindex". + +Definition BNP2 : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BNF12 : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__mul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiplication special cased for BNF12. + " in + let _ := M.assign_local (| + "mul" , + BinOp.mult (| + make_list [ + Constant.int 0 + ], + Constant.int 23 + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_subscript (| + M.get_name (| globals, locals_stack, "mul" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "self" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "right" |), + M.get_name (| globals, locals_stack, "j" |) + |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 22; + Constant.int 11; + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_subscript (| + M.get_name (| globals, locals_stack, "mul" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 6 + |) + |), + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mul" |), + M.get_name (| globals, locals_stack, "i" |) + |), + UnOp.sub (| Constant.int 18 |) + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_subscript (| + M.get_name (| globals, locals_stack, "mul" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 12 + |) + |), + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mul" |), + M.get_name (| globals, locals_stack, "i" |) + |), + Constant.int 82 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "__new__" |), + make_list [ + M.get_name (| globals, locals_stack, "BNF12" |); + M.slice (| + M.get_name (| globals, locals_stack, "mul" |), + Constant.None_, + Constant.int 12, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_98 : Value.t := + Constant.str "autoapi_noindex". + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_101 : Value.t := + Constant.str "autoapi_noindex". + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_104 : Value.t := + Constant.str "autoapi_noindex". + +Definition BNP12 : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition bnf2_to_bnf12 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Lift a field element in `BNF2` to `BNF12`. + " in + let _ := M.return_ (| + BinOp.add (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |), + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 1 + |) + ], + make_dict [] + |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "i_plus_9" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 9 + ], + make_dict [] + |) + |) + |) + |) + |) in + M.pure Constant.None_)). + +Axiom bnf2_to_bnf12_in_globals : + IsInGlobals globals "bnf2_to_bnf12" (make_function bnf2_to_bnf12). + +Definition bnp_to_bnp12 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "p" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Lift a point from `BNP` to `BNP12`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BNP12" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bnp_to_bnp12_in_globals : + IsInGlobals globals "bnp_to_bnp12" (make_function bnp_to_bnp12). + +Definition twist : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "p" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Apply to twist to change variables from the curve `BNP2` to `BNP12`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BNP12" |), + make_list [ + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "bnf2_to_bnf12" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |) + ], + make_dict [] + |), + BinOp.pow (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "w" |), + Constant.int 2 + |) + |); + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "bnf2_to_bnf12" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |) + ], + make_dict [] + |), + BinOp.pow (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "w" |), + Constant.int 3 + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom twist_in_globals : + IsInGlobals globals "twist" (make_function twist). + +Definition linefunc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "p1"; "p2"; "t" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "x" |), + M.get_field (| M.get_name (| globals, locals_stack, "p2" |), "x" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "lam" , + BinOp.div (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "p2" |), "y" |), + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "y" |) + |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "p2" |), "x" |), + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "x" |) + |) + |) + |) in + let _ := M.return_ (| + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "lam" |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "t" |), "x" |), + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "x" |) + |) + |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "t" |), "y" |), + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "y" |) + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "y" |), + M.get_field (| M.get_name (| globals, locals_stack, "p2" |), "y" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "lam" , + BinOp.div (| + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |), + BinOp.pow (| + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "x" |), + Constant.int 2 + |) + |), + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "y" |) + |) + |) + |) in + let _ := M.return_ (| + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "lam" |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "t" |), "x" |), + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "x" |) + |) + |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "t" |), "y" |), + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "y" |) + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "t" |), "x" |), + M.get_field (| M.get_name (| globals, locals_stack, "p1" |), "x" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom linefunc_in_globals : + IsInGlobals globals "linefunc" (make_function linefunc). + +Definition miller_loop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "q"; "p" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The core of the pairing algorithm. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP12" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP12" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "r" , + M.get_name (| globals, locals_stack, "q" |) + |) in + let _ := M.assign_local (| + "f" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "ATE_PAIRING_COUNT_BITS" |); + UnOp.sub (| Constant.int 1 |); + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "f" , + BinOp.mult (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "f" |), + M.get_name (| globals, locals_stack, "f" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "linefunc" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "r" |), "double" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BinOp.bit_and (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "ATE_PAIRING_COUNT" |), + Constant.int 1 + |), + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "i" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "f" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "f" |), + M.call (| + M.get_name (| globals, locals_stack, "linefunc" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "r" , + BinOp.add (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "q" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assert (| Compare.eq (| + M.get_name (| globals, locals_stack, "r" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "ATE_PAIRING_COUNT" |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) |) in + let _ := M.assign_local (| + "q1" , + M.call (| + M.get_name (| globals, locals_stack, "BNP12" |), + make_list [ + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "q" |), "x" |), "frobenius" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "q" |), "y" |), "frobenius" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "nq2" , + M.call (| + M.get_name (| globals, locals_stack, "BNP12" |), + make_list [ + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "q1" |), "x" |), "frobenius" |), + make_list [], + make_dict [] + |); + UnOp.sub (| M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "q1" |), "y" |), "frobenius" |), + make_list [], + make_dict [] + |) |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "f" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "f" |), + M.call (| + M.get_name (| globals, locals_stack, "linefunc" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "q1" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "r" , + BinOp.add (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "q1" |) + |) + |) in + let _ := M.assign_local (| + "f" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "f" |), + M.call (| + M.get_name (| globals, locals_stack, "linefunc" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "nq2" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "f" |), + BinOp.floor_div (| + BinOp.sub (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |), + Constant.int 12 + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + |) + |) + |) in + M.pure Constant.None_)). + +Axiom miller_loop_in_globals : + IsInGlobals globals "miller_loop" (make_function miller_loop). + +Definition pairing : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "q"; "p" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Compute the pairing of `q` and `p`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "miller_loop" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "twist" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "bnp_to_bnp12" |), + make_list [ + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pairing_in_globals : + IsInGlobals globals "pairing" (make_function pairing). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/crypto/blake2.md b/docs/revm-python-spec/revm-verif/spec-coq/crypto/blake2.md new file mode 100644 index 00000000..7e05e595 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/crypto/blake2.md @@ -0,0 +1,834 @@ +# ๐Ÿ“ blake2.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/crypto/blake2.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.crypto.blake2". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +The Blake2 Implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^ +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition spit_le_to_uint : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data"; "start"; "num_words" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "words" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_words" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "start_position" , + BinOp.add (| + M.get_name (| globals, locals_stack, "start" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 8 + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "words" |), "append" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_le_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "start_position" |), + Constant.int 8 + |), + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "words" |) + |) in + M.pure Constant.None_)). + +Axiom spit_le_to_uint_in_globals : + IsInGlobals globals "spit_le_to_uint" (make_function spit_le_to_uint). + +Definition Blake2 : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "get_blake2_parameters", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Extract the parameters required in the Blake2 compression function + from the provided bytes data. + + Parameters + ---------- + data : + The bytes data that has been passed in the message. + " in + let _ := M.assign_local (| + "rounds" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + Constant.None_, + Constant.int 4, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "h" , + M.call (| + M.get_name (| globals, locals_stack, "spit_le_to_uint" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + Constant.int 4; + Constant.int 8 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "m" , + M.call (| + M.get_name (| globals, locals_stack, "spit_le_to_uint" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + Constant.int 68; + Constant.int 16 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |) ], + M.call (| + M.get_name (| globals, locals_stack, "spit_le_to_uint" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + Constant.int 196; + Constant.int 2 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "f" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + Constant.int 212, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ] + |) in + M.pure Constant.None_)) + ); + ( + "G", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "v"; "a"; "b"; "c"; "d"; "x"; "y" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The mixing function used in Blake2 + https://datatracker.ietf.org/doc/html/rfc7693#section-3.1 + + Parameters + ---------- + v : + The working vector to be mixed. + a, b, c, d : + Indexes within v of the words to be mixed. + x, y : + The two input words for the mixing. + " in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "a" |) + |), + BinOp.mod_ (| + BinOp.add (| + BinOp.add (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "a" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "b" |) + |) + |), + M.get_name (| globals, locals_stack, "x" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "max_word" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "d" |) + |), + BinOp.bit_xor (| + BinOp.r_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "d" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "a" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "R1" |) + |), + BinOp.mod_ (| + BinOp.l_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "d" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "a" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "w_R1" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "max_word" |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "c" |) + |), + BinOp.mod_ (| + BinOp.add (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "c" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "d" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "max_word" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "b" |) + |), + BinOp.bit_xor (| + BinOp.r_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "b" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "c" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "R2" |) + |), + BinOp.mod_ (| + BinOp.l_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "b" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "c" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "w_R2" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "max_word" |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "a" |) + |), + BinOp.mod_ (| + BinOp.add (| + BinOp.add (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "a" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "b" |) + |) + |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "max_word" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "d" |) + |), + BinOp.bit_xor (| + BinOp.r_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "d" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "a" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "R3" |) + |), + BinOp.mod_ (| + BinOp.l_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "d" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "a" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "w_R3" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "max_word" |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "c" |) + |), + BinOp.mod_ (| + BinOp.add (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "c" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "d" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "max_word" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "b" |) + |), + BinOp.bit_xor (| + BinOp.r_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "b" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "c" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "R4" |) + |), + BinOp.mod_ (| + BinOp.l_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "b" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + M.get_name (| globals, locals_stack, "c" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "w_R4" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "max_word" |) + |) + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "v" |) + |) in + M.pure Constant.None_)) + ); + ( + "compress", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "num_rounds"; "h"; "m"; "t_0"; "t_1"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 'F Compression' from section 3.2 of RFC 7693: + https://tools.ietf.org/html/rfc7693#section-3.2 + + Parameters + ---------- + num_rounds : + The number of rounds. A 32-bit unsigned big-endian word + h : + The state vector. 8 unsigned 64-bit little-endian words + m : + The message block vector. 16 unsigned 64-bit little-endian words + t_0, t_1 : + Offset counters. 2 unsigned 64-bit little-endian words + f: + The final block indicator flag. An 8-bit word + " in + let _ := M.assign_local (| + "v" , + BinOp.mult (| + make_list [ + Constant.int 0 + ], + Constant.int 16 + |) + |) in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 0, + Constant.int 8, + Constant.None_ + |), + M.get_name (| globals, locals_stack, "h" |) + |) in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 8, + Constant.int 15, + Constant.None_ + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "IV" |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 12 + |), + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "t_0" |), + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "IV" |), + Constant.int 4 + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 13 + |), + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "t_1" |), + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "IV" |), + Constant.int 5 + |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "f" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 14 + |), + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 14 + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "mask_bits" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "r" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_rounds" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "s" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "sigma" |), + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "r" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "sigma_len" |) + |) + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "G" |), + make_list [ + M.get_name (| globals, locals_stack, "v" |); + Constant.int 0; + Constant.int 4; + Constant.int 8; + Constant.int 12; + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 0 + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 1 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "G" |), + make_list [ + M.get_name (| globals, locals_stack, "v" |); + Constant.int 1; + Constant.int 5; + Constant.int 9; + Constant.int 13; + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 2 + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 3 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "G" |), + make_list [ + M.get_name (| globals, locals_stack, "v" |); + Constant.int 2; + Constant.int 6; + Constant.int 10; + Constant.int 14; + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 4 + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 5 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "G" |), + make_list [ + M.get_name (| globals, locals_stack, "v" |); + Constant.int 3; + Constant.int 7; + Constant.int 11; + Constant.int 15; + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 6 + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 7 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "G" |), + make_list [ + M.get_name (| globals, locals_stack, "v" |); + Constant.int 0; + Constant.int 5; + Constant.int 10; + Constant.int 15; + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 8 + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 9 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "G" |), + make_list [ + M.get_name (| globals, locals_stack, "v" |); + Constant.int 1; + Constant.int 6; + Constant.int 11; + Constant.int 12; + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 10 + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 11 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "G" |), + make_list [ + M.get_name (| globals, locals_stack, "v" |); + Constant.int 2; + Constant.int 7; + Constant.int 8; + Constant.int 13; + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 12 + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 13 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "G" |), + make_list [ + M.get_name (| globals, locals_stack, "v" |); + Constant.int 3; + Constant.int 4; + Constant.int 9; + Constant.int 14; + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 14 + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "m" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "s" |), + Constant.int 15 + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "result_message_words" , + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "struct" |), "pack" |), + make_list_concat (| [ + make_list [ + BinOp.mod_ (| + Constant.str "<8%s", + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "word_format" |) + |) + ]; + M.get_name (| globals, locals_stack, "result_message_words" |) + ] |), + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition Blake2b : Value.t := make_klass {| + Klass.bases := [ + (globals, "Blake2") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/crypto/elliptic_curve.md b/docs/revm-python-spec/revm-verif/spec-coq/crypto/elliptic_curve.md new file mode 100644 index 00000000..401ded00 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/crypto/elliptic_curve.md @@ -0,0 +1,794 @@ +# ๐Ÿ“ elliptic_curve.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/crypto/elliptic_curve.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.crypto.elliptic_curve". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Elliptic Curves +^^^^^^^^^^^^^^^ +". + +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_crypto_finite_field_imports_Field : + IsImported globals "ethereum.crypto.finite_field" "Field". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Definition SECP256K1N : Value.t := M.run ltac:(M.monadic ( + Constant.int 115792089237316195423570985008687907852837564279074904382605163141518161494337 +)). + +Definition F : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "F" + ], + make_dict [] + |) +)). + +Definition T : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "T" + ], + make_dict [] + |) +)). + +Definition secp256k1_recover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "r"; "s"; "v"; "msg_hash" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "r_bytes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "r" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s_bytes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "s" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signature" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 0 + ], + Constant.int 65 + |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "signature" |), + BinOp.sub (| + Constant.int 32, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "r_bytes" |) + ], + make_dict [] + |) + |), + Constant.int 32, + Constant.None_ + |), + M.get_name (| globals, locals_stack, "r_bytes" |) + |) in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "signature" |), + BinOp.sub (| + Constant.int 64, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "s_bytes" |) + ], + make_dict [] + |) + |), + Constant.int 64, + Constant.None_ + |), + M.get_name (| globals, locals_stack, "s_bytes" |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "signature" |), + Constant.int 64 + |), + M.get_name (| globals, locals_stack, "v" |) + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "coincurve" |), "PublicKey" |), "from_signature_and_message" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "signature" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "msg_hash" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "public_key" , + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "public_key" |), "format" |), + make_list [], + make_dict [] + |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "public_key" |) + |) in + M.pure Constant.None_)). + +Axiom secp256k1_recover_in_globals : + IsInGlobals globals "secp256k1_recover" (make_function secp256k1_recover). + +Definition EllipticCurve : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ( + "point_at_infinity", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Return the point at infinity. This is the identity element of the group + operation. + + The point at infinity doesn't actually have coordinates so we use + `(0, 0)` (which isn't on the curve) to represent it. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; + Klass.methods := [ + ( + "__new__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "x"; "y" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Make new point on the curve. The point is not checked to see if it is + on the curve. + " in + let _ := M.assign_local (| + "res" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "object" |), "__new__" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "res" |), "x" |), + M.get_name (| globals, locals_stack, "x" |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "res" |), "y" |), + M.get_name (| globals, locals_stack, "y" |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "res" |) + |) in + M.pure Constant.None_)) + ); + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "x"; "y" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the point is on the curve. To skip this check call + `__new__()` directly. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + BoolOp.or (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "x" |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "y" |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + |) + )) + |), + ltac:(M.monadic ( + Compare.not_eq (| + BinOp.sub (| + BinOp.sub (| + BinOp.sub (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 2 + |), + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 3 + |) + |), + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "A" |), + M.get_name (| globals, locals_stack, "x" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "B" |) + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "ValueError" |), + make_list [ + Constant.str "Point not on curve" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)) + ); + ( + "__eq__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "other" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Test two points for equality. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "other" |); + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "x" |), + M.get_field (| M.get_name (| globals, locals_stack, "other" |), "x" |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "y" |), + M.get_field (| M.get_name (| globals, locals_stack, "other" |), "y" |) + |) + )) + |) + |) in + M.pure Constant.None_)) + ); + ( + "__str__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stringify a point as its coordinates. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "str" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "self" |), "x" |); M.get_field (| M.get_name (| globals, locals_stack, "self" |), "y" |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "double", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Add a point to itself. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "x" |); M.get_name (| globals, locals_stack, "y" |); M.get_name (| globals, locals_stack, "F" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "self" |), "x" |); M.get_field (| M.get_name (| globals, locals_stack, "self" |), "y" |); M.get_field (| M.get_name (| globals, locals_stack, "self" |), "FIELD" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "self" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "lam" , + BinOp.div (| + BinOp.add (| + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "F" |), "from_int" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |), + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "A" |) + |), + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "F" |), "from_int" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) + |) in + let _ := M.assign_local (| + "new_x" , + BinOp.sub (| + BinOp.sub (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "lam" |), + Constant.int 2 + |), + M.get_name (| globals, locals_stack, "x" |) + |), + M.get_name (| globals, locals_stack, "x" |) + |) + |) in + let _ := M.assign_local (| + "new_y" , + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "lam" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "new_x" |) + |) + |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "new_x" |); + M.get_name (| globals, locals_stack, "new_y" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "other" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Add two points together. + " in + let _ := M.assign_local (| + "ZERO" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "self_x" |); M.get_name (| globals, locals_stack, "self_y" |); M.get_name (| globals, locals_stack, "other_x" |); M.get_name (| globals, locals_stack, "other_y" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "self" |), "x" |); M.get_field (| M.get_name (| globals, locals_stack, "self" |), "y" |); M.get_field (| M.get_name (| globals, locals_stack, "other" |), "x" |); M.get_field (| M.get_name (| globals, locals_stack, "other" |), "y" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "self_x" |), + M.get_name (| globals, locals_stack, "ZERO" |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "self_y" |), + M.get_name (| globals, locals_stack, "ZERO" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "other" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "other_x" |), + M.get_name (| globals, locals_stack, "ZERO" |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "other_y" |), + M.get_name (| globals, locals_stack, "ZERO" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "self" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "self_x" |), + M.get_name (| globals, locals_stack, "other_x" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "self_y" |), + M.get_name (| globals, locals_stack, "other_y" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "double" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "lam" , + BinOp.div (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "other_y" |), + M.get_name (| globals, locals_stack, "self_y" |) + |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "other_x" |), + M.get_name (| globals, locals_stack, "self_x" |) + |) + |) + |) in + let _ := M.assign_local (| + "x" , + BinOp.sub (| + BinOp.sub (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "lam" |), + Constant.int 2 + |), + M.get_name (| globals, locals_stack, "self_x" |) + |), + M.get_name (| globals, locals_stack, "other_x" |) + |) + |) in + let _ := M.assign_local (| + "y" , + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "lam" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "self_x" |), + M.get_name (| globals, locals_stack, "x" |) + |) + |), + M.get_name (| globals, locals_stack, "self_y" |) + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "x" |); + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "mul_by", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "n" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply `self` by `n` using the double and add algorithm. + " in + let _ := M.assign_local (| + "res" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.get_name (| globals, locals_stack, "self" |) + |) in + let _ := + M.while (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "n" |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "n" |), + Constant.int 2 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "res" , + BinOp.add (| + M.get_name (| globals, locals_stack, "res" |), + M.get_name (| globals, locals_stack, "s" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "s" , + BinOp.add (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "s" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "n", + Constant.int 2 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "res" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/crypto/finite_field.md b/docs/revm-python-spec/revm-verif/spec-coq/crypto/finite_field.md new file mode 100644 index 00000000..264c2362 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/crypto/finite_field.md @@ -0,0 +1,2325 @@ +# ๐Ÿ“ finite_field.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/crypto/finite_field.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.crypto.finite_field". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Finite Fields +^^^^^^^^^^^^^ +". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom typing_extensions_imports_Protocol : + IsImported globals "typing_extensions" "Protocol". + +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". + +Definition F : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "F" + ], + make_dict [] + |) +)). + +Definition Field : Value.t := make_klass {| + Klass.bases := [ + (globals, "Protocol") + ]; + Klass.class_methods := [ + ( + "zero", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "from_int", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "n" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ) + ]; + Klass.methods := [ + ( + "__radd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__iadd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__sub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__rsub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__mul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__rmul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__imul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__pow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "exponent" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__ipow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__neg__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__truediv__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition T : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "T" + ], + make_dict [] + |) +)). + +Definition PrimeField : Value.t := make_klass {| + Klass.bases := [ + (globals, "int"); + (globals, "Field") + ]; + Klass.class_methods := [ + ( + "from_be_bytes", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "buffer" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts a sequence of bytes into a element of the field. + Parameters + ---------- + buffer : + Bytes to decode. + Returns + ------- + self : `T` + Unsigned integer decoded from `buffer`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "from_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |); + Constant.str "big" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "zero", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "from_int", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "n" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; + Klass.methods := [ + ( + "__new__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "value" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__new__" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "PRIME" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__radd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__iadd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__sub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__sub__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rsub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__rsub__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__mul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.get_name (| globals, locals_stack, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |); + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rmul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__imul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__pow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "exponent" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__pow__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "PRIME" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__ipow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__pow__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__neg__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "int" |), "__neg__" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__truediv__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "self" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "right" |), "multiplicative_inverse" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "multiplicative_inverse", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "self" |), + UnOp.sub (| Constant.int 1 |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "to_be_bytes32", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Converts this arbitrarily sized unsigned integer into its big endian + representation with exactly 32 bytes. + Returns + ------- + big_endian : `Bytes32` + Big endian (most significant bits first) representation. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes32" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "to_bytes" |), + make_list [ + Constant.int 32; + Constant.str "big" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition U : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "U" + ], + make_dict [] + |) +)). + +Definition GaloisField : Value.t := make_klass {| + Klass.bases := [ + (globals, "tuple"); + (globals, "Field") + ]; + Klass.class_methods := [ + ( + "zero", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + BinOp.mult (| + make_list [ + Constant.int 0 + ], + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "MODULUS" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "from_int", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "n" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + BinOp.add (| + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + BinOp.mult (| + make_list [ + Constant.int 0 + ], + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "MODULUS" |) + ], + make_dict [] + |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "calculate_frobenius_coefficients", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the coefficients needed by `frobenius()`. + " in + let _ := M.assign_local (| + "coefficients" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "MODULUS" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "x" , + BinOp.mult (| + make_list [ + Constant.int 0 + ], + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "MODULUS" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |), + Constant.int 1 + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "coefficients" |), "append" |), + make_list [ + BinOp.pow (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "PRIME" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [ + M.get_name (| globals, locals_stack, "coefficients" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; + Klass.methods := [ + ( + "__new__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "iterable" ] in + ltac:(M.monadic ( + let _ := M.assign_local (| + "self" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "tuple" |), "__new__" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + let _ := M.assert (| Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "MODULUS" |) + ], + make_dict [] + |) + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "self" |) + |) in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__radd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__iadd__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__sub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |); + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rsub__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |); + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__mul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.assign_local (| + "modulus" , + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MODULUS" |) + |) in + let _ := M.assign_local (| + "degree" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "prime" , + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "PRIME" |) + |) in + let _ := M.assign_local (| + "mul" , + BinOp.mult (| + make_list [ + Constant.int 0 + ], + BinOp.mult (| + M.get_name (| globals, locals_stack, "degree" |), + Constant.int 2 + |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "degree" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "degree" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_subscript (| + M.get_name (| globals, locals_stack, "mul" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "self" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "right" |), + M.get_name (| globals, locals_stack, "j" |) + |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "degree" |), + Constant.int 2 + |), + Constant.int 1 + |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "degree" |), + Constant.int 1 + |); + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "degree" |) + |); + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_subscript (| + M.get_name (| globals, locals_stack, "mul" |), + M.get_name (| globals, locals_stack, "j" |) + |), + BinOp.mod_ (| + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mul" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "modulus" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "degree" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "j" |) + |) + |) + |) + |), + M.get_name (| globals, locals_stack, "prime" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.slice (| + M.get_name (| globals, locals_stack, "mul" |), + Constant.None_, + M.get_name (| globals, locals_stack, "degree" |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rmul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "left" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__imul__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__truediv__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "self" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "right" |), "multiplicative_inverse" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "__neg__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "scalar_mul", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "x" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply a field element by a integer. This is faster than using + `from_int()` and field multiplication. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "deg", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + This is a support function for `multiplicative_inverse()`. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MODULUS" |) + ], + make_dict [] + |), + Constant.int 1 + |); + UnOp.sub (| Constant.int 1 |); + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "self" |), + M.get_name (| globals, locals_stack, "i" |) + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "ValueError" |), + make_list [ + Constant.str "deg() does not support zero" + ], + make_dict [] + |)) |) in + M.pure Constant.None_)) + ); + ( + "multiplicative_inverse", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the multiplicative inverse. Uses the Euclidean algorithm. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "p" , + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "PRIME" |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "x1" |); M.get_name (| globals, locals_stack, "f1" |) ], + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "list" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MODULUS" |) + ], + make_dict [] + |); BinOp.mult (| + make_list [ + Constant.int 0 + ], + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |) + |) ] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "x2" |); M.get_name (| globals, locals_stack, "f2" |); M.get_name (| globals, locals_stack, "d2" |) ], + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "list" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); BinOp.add (| + make_list [ + Constant.int 1 + ], + BinOp.mult (| + make_list [ + Constant.int 0 + ], + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |), + Constant.int 1 + |) + |) + |); M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "deg" |), + make_list [], + make_dict [] + |) ] + |) in + let _ := M.assign_local (| + "q_0" , + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "x2" |), + M.get_name (| globals, locals_stack, "d2" |) + |); + UnOp.sub (| Constant.int 1 |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "d2" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x1" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "d2" |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x1" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "d2" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "q_0" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x2" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + |), + M.get_name (| globals, locals_stack, "p" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "f1" |), + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x1" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "d2" |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "f1" |), + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x1" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "d2" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "q_0" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "f2" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + |), + M.get_name (| globals, locals_stack, "p" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MODULUS" |) + ], + make_dict [] + |), + Constant.int 1 + |); + UnOp.sub (| Constant.int 1 |); + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + M.get_name (| globals, locals_stack, "i" |) + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "d1" , + M.get_name (| globals, locals_stack, "i" |) + |) in + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.while (| + Constant.bool true, + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "d1" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "ans" , + M.get_name (| globals, locals_stack, "f1" |) + |) in + let _ := M.assign_local (| + "q" , + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + Constant.int 0 + |); + UnOp.sub (| Constant.int 1 |); + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "PRIME" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ans" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.mult, + M.get_subscript (| + M.get_name (| globals, locals_stack, "ans" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_name (| globals, locals_stack, "q" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "d2" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "ans" , + M.get_name (| globals, locals_stack, "f2" |) + |) in + let _ := M.assign_local (| + "q" , + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "x2" |), + Constant.int 0 + |); + UnOp.sub (| Constant.int 1 |); + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "PRIME" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ans" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.mult, + "ans", + M.get_name (| globals, locals_stack, "q" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "d1" |), + M.get_name (| globals, locals_stack, "d2" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "q" , + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x2" |), + M.get_name (| globals, locals_stack, "d2" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + M.get_name (| globals, locals_stack, "d1" |) + |); + UnOp.sub (| Constant.int 1 |); + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "PRIME" |) + ], + make_dict [] + |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MODULUS" |) + ], + make_dict [] + |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d2" |), + M.get_name (| globals, locals_stack, "d1" |) + |) + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x2" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d2" |), + M.get_name (| globals, locals_stack, "d1" |) + |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x2" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d2" |), + M.get_name (| globals, locals_stack, "d1" |) + |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "q" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + |), + M.get_name (| globals, locals_stack, "p" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "f2" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d2" |), + M.get_name (| globals, locals_stack, "d1" |) + |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "f2" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d2" |), + M.get_name (| globals, locals_stack, "d1" |) + |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "q" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "f1" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + |), + M.get_name (| globals, locals_stack, "p" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.while (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x2" |), + M.get_name (| globals, locals_stack, "d2" |) + |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "d2", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "q" , + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + M.get_name (| globals, locals_stack, "d1" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "x2" |), + M.get_name (| globals, locals_stack, "d2" |) + |); + UnOp.sub (| Constant.int 1 |); + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "PRIME" |) + ], + make_dict [] + |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MODULUS" |) + ], + make_dict [] + |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d1" |), + M.get_name (| globals, locals_stack, "d2" |) + |) + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d1" |), + M.get_name (| globals, locals_stack, "d2" |) + |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d1" |), + M.get_name (| globals, locals_stack, "d2" |) + |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "q" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x2" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + |), + M.get_name (| globals, locals_stack, "p" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "f1" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d1" |), + M.get_name (| globals, locals_stack, "d2" |) + |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "f1" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "d1" |), + M.get_name (| globals, locals_stack, "d2" |) + |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "q" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "f2" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + |), + M.get_name (| globals, locals_stack, "p" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.while (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "x1" |), + M.get_name (| globals, locals_stack, "d1" |) + |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "d1", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "ans" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__pow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "exponent" ] in + ltac:(M.monadic ( + let _ := M.assign_local (| + "degree" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "MODULUS" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "exponent" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "self" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "multiplicative_inverse" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + UnOp.sub (| M.get_name (| globals, locals_stack, "exponent" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "res" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |); + BinOp.add (| + make_list [ + Constant.int 1 + ], + BinOp.mult (| + make_list [ + Constant.int 0 + ], + BinOp.sub (| + M.get_name (| globals, locals_stack, "degree" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.get_name (| globals, locals_stack, "self" |) + |) in + let _ := + M.while (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "exponent" |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "exponent" |), + Constant.int 2 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.mult, + "res", + M.get_name (| globals, locals_stack, "s" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.mult, + "s", + M.get_name (| globals, locals_stack, "s" |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "exponent", + Constant.int 2 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "res" |) + |) in + M.pure Constant.None_)) + ); + ( + "__ipow__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "right" ] in + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "__pow__" |), + make_list [ + M.get_name (| globals, locals_stack, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "frobenius", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns `self ** p`. This function is known as the Frobenius + endomorphism and has many special mathematical properties. In + particular it is extremely cheap to compute compared to other + exponentiations. + " in + let _ := M.assign_local (| + "ans" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "from_int" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "a" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "self" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "ans", + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_name (| globals, locals_stack, "U" |); + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "FROBENIUS_COEFFICIENTS" |), + M.get_name (| globals, locals_stack, "i" |) + |) + ], + make_dict [] + |), "scalar_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "ans" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/crypto/hash.md b/docs/revm-python-spec/revm-verif/spec-coq/crypto/hash.md new file mode 100644 index 00000000..af967d21 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/crypto/hash.md @@ -0,0 +1,142 @@ +# ๐Ÿ“ hash.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/crypto/hash.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.crypto.hash". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Cryptographic Hash Functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Cryptographic hashing functions. +". + +Axiom Crypto_Hash_imports_keccak : + IsImported globals "Crypto.Hash" "keccak". + +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Bytes64 : + IsImported globals "ethereum.base_types" "Bytes64". + +Definition Hash32 : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes32" |) +)). + +Definition Hash64 : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes64" |) +)). + +Definition keccak256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "k" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "keccak" |), "new" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "k" |), "update" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom keccak256_in_globals : + IsInGlobals globals "keccak256" (make_function keccak256). + +Definition keccak512 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "k" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "keccak" |), "new" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Hash64" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "k" |), "update" |), + make_list [ + M.get_name (| globals, locals_stack, "buffer" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom keccak512_in_globals : + IsInGlobals globals "keccak512" (make_function keccak512). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/crypto/simulations/hash.md b/docs/revm-python-spec/revm-verif/spec-coq/crypto/simulations/hash.md new file mode 100644 index 00000000..6aa2c7cb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/crypto/simulations/hash.md @@ -0,0 +1,32 @@ +# ๐Ÿ“ hash.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/crypto/simulations/hash.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Require ethereum.simulations.base_types. +Module Bytes := base_types.Bytes. +Module Bytes32 := base_types.Bytes32. +Module Bytes64 := base_types.Bytes64. + +Module Hash32. + Inductive t : Set := + | Make (hash : Bytes32.t). + + Definition get (hash : t) : Bytes32.t := + match hash with + | Make hash => hash + end. +End Hash32. + +Module Hash64. + Inductive t : Set := + | Make (hash : Bytes64.t). + + Definition get (hash : t) : Bytes64.t := + match hash with + | Make hash => hash + end. +End Hash64. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/__init__.md new file mode 100644 index 00000000..c8d6738f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/__init__.md @@ -0,0 +1,31 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 1920000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/blocks.md new file mode 100644 index 00000000..37be5e6b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/blocks.md @@ -0,0 +1,91 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Bloom : + IsImported globals "ethereum.dao_fork.fork_types" "Bloom". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". + +Axiom ethereum_dao_fork_transactions_imports_Transaction : + IsImported globals "ethereum.dao_fork.transactions" "Transaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/bloom.md new file mode 100644 index 00000000..c8352a2d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". + +Axiom ethereum_dao_fork_fork_types_imports_Bloom : + IsImported globals "ethereum.dao_fork.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/dao.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/dao.md new file mode 100644 index 00000000..ca9f0efe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/dao.md @@ -0,0 +1,102 @@ +# ๐Ÿ“ dao.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/dao.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.dao". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_dao_fork_state_imports_State : + IsImported globals "ethereum.dao_fork.state" "State". +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". +Axiom ethereum_dao_fork_state_imports_move_ether : + IsImported globals "ethereum.dao_fork.state" "move_ether". + +Axiom ethereum_dao_fork_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.dao_fork.utils.hexadecimal" "hex_to_address". + +Definition DAO_ACCOUNTS : Value.t := M.run ltac:(M.monadic ( + Constant.str "(* At expr: unsupported node type: ListComp *)" +)). + +Definition DAO_RECOVERY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0xbf4ed7b27f1d666546e30d74d50d173d20bca754" + ], + make_dict [] + |) +)). + +Definition apply_dao : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Apply the dao fork to the state. + + Parameters + ---------- + state : + State before applying the DAO Fork. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_name (| globals, locals_stack, "DAO_ACCOUNTS" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "DAO_RECOVERY" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom apply_dao_in_globals : + IsInGlobals globals "apply_dao" (make_function apply_dao). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/fork.md new file mode 100644 index 00000000..afb3370b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/fork.md @@ -0,0 +1,2691 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +.. _dao-fork: + +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_imports_FORK_CRITERIA : + IsImported globals "ethereum.dao_fork" "FORK_CRITERIA". +Axiom ethereum_dao_fork_imports_vm : + IsImported globals "ethereum.dao_fork" "vm". + +Axiom ethereum_dao_fork_blocks_imports_Block : + IsImported globals "ethereum.dao_fork.blocks" "Block". +Axiom ethereum_dao_fork_blocks_imports_Header : + IsImported globals "ethereum.dao_fork.blocks" "Header". +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". +Axiom ethereum_dao_fork_blocks_imports_Receipt : + IsImported globals "ethereum.dao_fork.blocks" "Receipt". + +Axiom ethereum_dao_fork_bloom_imports_logs_bloom : + IsImported globals "ethereum.dao_fork.bloom" "logs_bloom". + +Axiom ethereum_dao_fork_dao_imports_apply_dao : + IsImported globals "ethereum.dao_fork.dao" "apply_dao". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Bloom : + IsImported globals "ethereum.dao_fork.fork_types" "Bloom". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". + +Axiom ethereum_dao_fork_state_imports_State : + IsImported globals "ethereum.dao_fork.state" "State". +Axiom ethereum_dao_fork_state_imports_create_ether : + IsImported globals "ethereum.dao_fork.state" "create_ether". +Axiom ethereum_dao_fork_state_imports_destroy_account : + IsImported globals "ethereum.dao_fork.state" "destroy_account". +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". +Axiom ethereum_dao_fork_state_imports_increment_nonce : + IsImported globals "ethereum.dao_fork.state" "increment_nonce". +Axiom ethereum_dao_fork_state_imports_set_account_balance : + IsImported globals "ethereum.dao_fork.state" "set_account_balance". +Axiom ethereum_dao_fork_state_imports_state_root : + IsImported globals "ethereum.dao_fork.state" "state_root". + +Axiom ethereum_dao_fork_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.dao_fork.transactions" "TX_BASE_COST". +Axiom ethereum_dao_fork_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.dao_fork.transactions" "TX_CREATE_COST". +Axiom ethereum_dao_fork_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.dao_fork.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_dao_fork_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.dao_fork.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_dao_fork_transactions_imports_Transaction : + IsImported globals "ethereum.dao_fork.transactions" "Transaction". + +Axiom ethereum_dao_fork_trie_imports_Trie : + IsImported globals "ethereum.dao_fork.trie" "Trie". +Axiom ethereum_dao_fork_trie_imports_root : + IsImported globals "ethereum.dao_fork.trie" "root". +Axiom ethereum_dao_fork_trie_imports_trie_set : + IsImported globals "ethereum.dao_fork.trie" "trie_set". + +Axiom ethereum_dao_fork_utils_message_imports_prepare_message : + IsImported globals "ethereum.dao_fork.utils.message" "prepare_message". + +Axiom ethereum_dao_fork_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.dao_fork.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "apply_dao" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "old" |), "state" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "FORK_CRITERIA" |), "block_number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "FORK_CRITERIA" |), "block_number" |), + Constant.int 10 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |), + Constant.bytes "64616f2d686172642d666f726b" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "v" |); M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_in_globals : + IsInGlobals globals "signing_hash" (make_function signing_hash). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + Constant.int 1, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 10 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/fork_types.md new file mode 100644 index 00000000..d4c499b2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/state.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/state.md new file mode 100644 index 00000000..3daa20ab --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/state.md @@ -0,0 +1,998 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_dao_fork_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.dao_fork.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_dao_fork_fork_types_imports_Account : + IsImported globals "ethereum.dao_fork.fork_types" "Account". +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". + +Axiom ethereum_dao_fork_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.dao_fork.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_dao_fork_trie_imports_Trie : + IsImported globals "ethereum.dao_fork.trie" "Trie". +Axiom ethereum_dao_fork_trie_imports_copy_trie : + IsImported globals "ethereum.dao_fork.trie" "copy_trie". +Axiom ethereum_dao_fork_trie_imports_root : + IsImported globals "ethereum.dao_fork.trie" "root". +Axiom ethereum_dao_fork_trie_imports_trie_get : + IsImported globals "ethereum.dao_fork.trie" "trie_get". +Axiom ethereum_dao_fork_trie_imports_trie_set : + IsImported globals "ethereum.dao_fork.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/transactions.md new file mode 100644 index 00000000..8a1b8406 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/transactions.md @@ -0,0 +1,63 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/trie.md new file mode 100644 index 00000000..ebb89563 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/trie.md @@ -0,0 +1,1639 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_homestead_imports_trie : + IsImported globals "ethereum.homestead" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_dao_fork_blocks_imports_Receipt : + IsImported globals "ethereum.dao_fork.blocks" "Receipt". + +Axiom ethereum_dao_fork_fork_types_imports_Account : + IsImported globals "ethereum.dao_fork.fork_types" "Account". +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". +Axiom ethereum_dao_fork_fork_types_imports_encode_account : + IsImported globals "ethereum.dao_fork.fork_types" "encode_account". + +Axiom ethereum_dao_fork_transactions_imports_Transaction : + IsImported globals "ethereum.dao_fork.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Receipt" |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/__init__.md new file mode 100644 index 00000000..0ac5ba32 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/address.md new file mode 100644 index 00000000..21652351 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/address.md @@ -0,0 +1,159 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this Dao Fork version of specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/hexadecimal.md new file mode 100644 index 00000000..e17784db --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Bloom : + IsImported globals "ethereum.dao_fork.fork_types" "Bloom". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/message.md new file mode 100644 index 00000000..01155cb3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/utils/message.md @@ -0,0 +1,220 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". + +Axiom ethereum_dao_fork_vm_imports_Environment : + IsImported globals "ethereum.dao_fork.vm" "Environment". +Axiom ethereum_dao_fork_vm_imports_Message : + IsImported globals "ethereum.dao_fork.vm" "Message". + +Axiom ethereum_dao_fork_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.dao_fork.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/__init__.md new file mode 100644 index 00000000..c4c73544 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/__init__.md @@ -0,0 +1,151 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_State : + IsImported globals "ethereum.dao_fork.state" "State". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/exceptions.md new file mode 100644 index 00000000..46642eba --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/exceptions.md @@ -0,0 +1,131 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/gas.md new file mode 100644 index 00000000..79c8447f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/gas.md @@ -0,0 +1,874 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_State : + IsImported globals "ethereum.dao_fork.state" "State". +Axiom ethereum_dao_fork_state_imports_account_exists : + IsImported globals "ethereum.dao_fork.state" "account_exists". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 40 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "gas"; "to"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "gas" |) + |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + |) in + let _ := M.assign_local (| + "stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "gas" |) + (* else *) + )), ltac:(M.monadic ( +BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |), + M.get_name (| globals, locals_stack, "gas" |) + |) + )) |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + M.get_name (| globals, locals_stack, "cost" |); + M.get_name (| globals, locals_stack, "stipend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/__init__.md new file mode 100644 index 00000000..bd907e6d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_dao_fork_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.dao_fork.vm.instructions" "arithmetic". + +Axiom ethereum_dao_fork_vm_instructions_imports_bitwise : + IsImported globals "ethereum.dao_fork.vm.instructions" "bitwise". + +Axiom ethereum_dao_fork_vm_instructions_imports_block : + IsImported globals "ethereum.dao_fork.vm.instructions" "block". + +Axiom ethereum_dao_fork_vm_instructions_imports_comparison : + IsImported globals "ethereum.dao_fork.vm.instructions" "comparison". + +Axiom ethereum_dao_fork_vm_instructions_imports_control_flow : + IsImported globals "ethereum.dao_fork.vm.instructions" "control_flow". + +Axiom ethereum_dao_fork_vm_instructions_imports_environment : + IsImported globals "ethereum.dao_fork.vm.instructions" "environment". + +Axiom ethereum_dao_fork_vm_instructions_imports_keccak : + IsImported globals "ethereum.dao_fork.vm.instructions" "keccak". + +Axiom ethereum_dao_fork_vm_instructions_imports_log : + IsImported globals "ethereum.dao_fork.vm.instructions" "log". + +Axiom ethereum_dao_fork_vm_instructions_imports_memory : + IsImported globals "ethereum.dao_fork.vm.instructions" "memory". + +Axiom ethereum_dao_fork_vm_instructions_imports_stack : + IsImported globals "ethereum.dao_fork.vm.instructions" "stack". + +Axiom ethereum_dao_fork_vm_instructions_imports_storage : + IsImported globals "ethereum.dao_fork.vm.instructions" "storage". + +Axiom ethereum_dao_fork_vm_instructions_imports_system : + IsImported globals "ethereum.dao_fork.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/arithmetic.md new file mode 100644 index 00000000..8e498cbb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_MID". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/bitwise.md new file mode 100644 index 00000000..1747f876 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/bitwise.md @@ -0,0 +1,400 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/block.md new file mode 100644 index 00000000..045f888a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/block.md @@ -0,0 +1,380 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/comparison.md new file mode 100644 index 00000000..46957e77 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/control_flow.md new file mode 100644 index 00000000..e18f0dc7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_HIGH". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_MID". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/environment.md new file mode 100644 index 00000000..e144c1ca --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/environment.md @@ -0,0 +1,1053 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". + +Axiom ethereum_dao_fork_utils_address_imports_to_address : + IsImported globals "ethereum.dao_fork.utils.address" "to_address". + +Axiom ethereum_dao_fork_vm_memory_imports_buffer_read : + IsImported globals "ethereum.dao_fork.vm.memory" "buffer_read". +Axiom ethereum_dao_fork_vm_memory_imports_memory_write : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_write". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BALANCE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_COPY". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/keccak.md new file mode 100644 index 00000000..85bd0162 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_KECCAK256". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_read_bytes". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/log.md new file mode 100644 index 00000000..50562962 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/log.md @@ -0,0 +1,254 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_LOG". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_read_bytes". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/memory.md new file mode 100644 index 00000000..64af8884 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_read_bytes". +Axiom ethereum_dao_fork_vm_memory_imports_memory_write : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_write". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/stack.md new file mode 100644 index 00000000..873d8a17 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". +Axiom ethereum_dao_fork_vm_imports_stack : + IsImported globals "ethereum.dao_fork.vm" "stack". + +Axiom ethereum_dao_fork_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_buffer_read : + IsImported globals "ethereum.dao_fork.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/storage.md new file mode 100644 index 00000000..51ea2cda --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/storage.md @@ -0,0 +1,250 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_dao_fork_state_imports_get_storage : + IsImported globals "ethereum.dao_fork.state" "get_storage". +Axiom ethereum_dao_fork_state_imports_set_storage : + IsImported globals "ethereum.dao_fork.state" "set_storage". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_SLOAD". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/system.md new file mode 100644 index 00000000..fa0d0c28 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/instructions/system.md @@ -0,0 +1,1420 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.dao_fork.state" "account_has_code_or_nonce". +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". +Axiom ethereum_dao_fork_state_imports_increment_nonce : + IsImported globals "ethereum.dao_fork.state" "increment_nonce". +Axiom ethereum_dao_fork_state_imports_set_account_balance : + IsImported globals "ethereum.dao_fork.state" "set_account_balance". + +Axiom ethereum_dao_fork_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.dao_fork.utils.address" "compute_contract_address". +Axiom ethereum_dao_fork_utils_address_imports_to_address : + IsImported globals "ethereum.dao_fork.utils.address" "to_address". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". +Axiom ethereum_dao_fork_vm_imports_Message : + IsImported globals "ethereum.dao_fork.vm" "Message". +Axiom ethereum_dao_fork_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.dao_fork.vm" "incorporate_child_on_error". +Axiom ethereum_dao_fork_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.dao_fork.vm" "incorporate_child_on_success". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_CALL". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_CREATE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_ZERO". +Axiom ethereum_dao_fork_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.dao_fork.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_message_call_gas". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_read_bytes". +Axiom ethereum_dao_fork_vm_memory_imports_memory_write : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_write". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_ZERO" |) + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "gas" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/interpreter.md new file mode 100644 index 00000000..4679fc0e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/interpreter.md @@ -0,0 +1,593 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.dao_fork.state" "account_has_code_or_nonce". +Axiom ethereum_dao_fork_state_imports_begin_transaction : + IsImported globals "ethereum.dao_fork.state" "begin_transaction". +Axiom ethereum_dao_fork_state_imports_commit_transaction : + IsImported globals "ethereum.dao_fork.state" "commit_transaction". +Axiom ethereum_dao_fork_state_imports_move_ether : + IsImported globals "ethereum.dao_fork.state" "move_ether". +Axiom ethereum_dao_fork_state_imports_rollback_transaction : + IsImported globals "ethereum.dao_fork.state" "rollback_transaction". +Axiom ethereum_dao_fork_state_imports_set_code : + IsImported globals "ethereum.dao_fork.state" "set_code". +Axiom ethereum_dao_fork_state_imports_touch_account : + IsImported globals "ethereum.dao_fork.state" "touch_account". + +Axiom ethereum_dao_fork_vm_imports_Message : + IsImported globals "ethereum.dao_fork.vm" "Message". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_dao_fork_vm_imports_Environment : + IsImported globals "ethereum.dao_fork.vm" "Environment". +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.dao_fork.vm.exceptions" "AddressCollision". +Axiom ethereum_dao_fork_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.dao_fork.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_dao_fork_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.dao_fork.vm.exceptions" "InvalidOpcode". +Axiom ethereum_dao_fork_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_dao_fork_vm_instructions_imports_Ops : + IsImported globals "ethereum.dao_fork.vm.instructions" "Ops". +Axiom ethereum_dao_fork_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.dao_fork.vm.instructions" "op_implementation". + +Axiom ethereum_dao_fork_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.dao_fork.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/memory.md new file mode 100644 index 00000000..b66b1f74 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..32c231a3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/__init__.md @@ -0,0 +1,74 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_dao_fork_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.dao_fork.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..1dfbe2f3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_buffer_read : + IsImported globals "ethereum.dao_fork.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..ab2ad514 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_IDENTITY". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..69b085bd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/mapping.md @@ -0,0 +1,57 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_dao_fork_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_dao_fork_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_dao_fork_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..1d165f23 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..c48e9f7a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_SHA256". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/runtime.md new file mode 100644 index 00000000..e493fe93 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_vm_instructions_imports_Ops : + IsImported globals "ethereum.dao_fork.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/stack.md new file mode 100644 index 00000000..298ace4e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/dao_fork/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/dao_fork/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.dao_fork.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "StackOverflowError". +Axiom ethereum_dao_fork_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/ethash.md b/docs/revm-python-spec/revm-verif/spec-coq/ethash.md new file mode 100644 index 00000000..909071ad --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/ethash.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ ethash.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/./ethash.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.ethash". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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 +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U32 : + IsImported globals "ethereum.base_types" "U32". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_Hash64 : + IsImported globals "ethereum.crypto.hash" "Hash64". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". +Axiom ethereum_crypto_hash_imports_keccak512 : + IsImported globals "ethereum.crypto.hash" "keccak512". + +Axiom ethereum_utils_numeric_imports_is_prime : + IsImported globals "ethereum.utils.numeric" "is_prime". +Axiom ethereum_utils_numeric_imports_le_bytes_to_uint32_sequence : + IsImported globals "ethereum.utils.numeric" "le_bytes_to_uint32_sequence". +Axiom ethereum_utils_numeric_imports_le_uint32_sequence_to_bytes : + IsImported globals "ethereum.utils.numeric" "le_uint32_sequence_to_bytes". +Axiom ethereum_utils_numeric_imports_le_uint32_sequence_to_uint : + IsImported globals "ethereum.utils.numeric" "le_uint32_sequence_to_uint". + +Definition EPOCH_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 30000 +)). + +Definition expr_41 : Value.t := + Constant.str " +Number of blocks before a dataset needs to be regenerated (known as an +""epoch"".) See [`epoch`]. + +[`epoch`]: ref:ethereum.ethash.epoch +". + +Definition INITIAL_CACHE_SIZE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 24 + |) +)). + +Definition expr_49 : Value.t := + Constant.str " +Size of the cache (in bytes) during the first epoch. Each subsequent epoch's +cache roughly grows by [`CACHE_EPOCH_GROWTH_SIZE`] bytes. See [`cache_size`]. + +[`CACHE_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.CACHE_EPOCH_GROWTH_SIZE +[`cache_size`]: ref:ethereum.ethash.cache_size +". + +Definition CACHE_EPOCH_GROWTH_SIZE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 17 + |) +)). + +Definition expr_58 : Value.t := + Constant.str " +After the first epoch, the cache size grows by roughly this amount. See +[`cache_size`]. + +[`cache_size`]: ref:ethereum.ethash.cache_size +". + +Definition INITIAL_DATASET_SIZE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 30 + |) +)). + +Definition expr_66 : Value.t := + Constant.str " +Size of the dataset (in bytes) during the first epoch. Each subsequent epoch's +dataset roughly grows by [`DATASET_EPOCH_GROWTH_SIZE`] bytes. See +[`dataset_size`]. + +[`DATASET_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE +[`dataset_size`]: ref:ethereum.ethash.dataset_size +". + +Definition DATASET_EPOCH_GROWTH_SIZE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 23 + |) +)). + +Definition expr_76 : Value.t := + Constant.str " +After the first epoch, the dataset size grows by roughly this amount. See +[`dataset_size`]. + +[`dataset_size`]: ref:ethereum.ethash.dataset_size +". + +Definition HASH_BYTES : Value.t := M.run ltac:(M.monadic ( + Constant.int 64 +)). + +Definition expr_84 : Value.t := + Constant.str " +Length of a hash, in bytes. +". + +Definition MIX_BYTES : Value.t := M.run ltac:(M.monadic ( + Constant.int 128 +)). + +Definition expr_89 : Value.t := + Constant.str " +Width of mix, in bytes. See [`generate_dataset_item`]. + +[`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item +". + +Definition CACHE_ROUNDS : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition expr_96 : Value.t := + Constant.str " +Number of times to repeat the [`keccak512`] step while generating the hash. See +[`generate_cache`]. + +[`keccak512`]: ref:ethereum.crypto.hash.keccak512 +[`generate_cache`]: ref:ethereum.ethash.generate_cache +". + +Definition DATASET_PARENTS : Value.t := M.run ltac:(M.monadic ( + Constant.int 256 +)). + +Definition expr_105 : Value.t := + Constant.str " +Number of parents of each dataset element. See [`generate_dataset_item`]. + +[`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item +". + +Definition HASHIMOTO_ACCESSES : Value.t := M.run ltac:(M.monadic ( + Constant.int 64 +)). + +Definition expr_112 : Value.t := + Constant.str " +Number of accesses in the [`hashimoto`] loop. + +[`hashimoto`]: ref:ethereum.ethash.hashimoto +". + +Definition epoch : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_name (| globals, locals_stack, "EPOCH_SIZE" |) + |) + |) in + M.pure Constant.None_)). + +Axiom epoch_in_globals : + IsInGlobals globals "epoch" (make_function epoch). + +Definition cache_size : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "size" , + BinOp.add (| + M.get_name (| globals, locals_stack, "INITIAL_CACHE_SIZE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "CACHE_EPOCH_GROWTH_SIZE" |), + M.call (| + M.get_name (| globals, locals_stack, "epoch" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |) + |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "size", + M.get_name (| globals, locals_stack, "HASH_BYTES" |) + |) in + let _ := + M.while (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_prime" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "size" |), + M.get_name (| globals, locals_stack, "HASH_BYTES" |) + |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "size", + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "HASH_BYTES" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "size" |) + |) in + M.pure Constant.None_)). + +Axiom cache_size_in_globals : + IsInGlobals globals "cache_size" (make_function cache_size). + +Definition dataset_size : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "size" , + BinOp.add (| + M.get_name (| globals, locals_stack, "INITIAL_DATASET_SIZE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "DATASET_EPOCH_GROWTH_SIZE" |), + M.call (| + M.get_name (| globals, locals_stack, "epoch" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |) + |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "size", + M.get_name (| globals, locals_stack, "MIX_BYTES" |) + |) in + let _ := + M.while (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_prime" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "size" |), + M.get_name (| globals, locals_stack, "MIX_BYTES" |) + |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "size", + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "MIX_BYTES" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "size" |) + |) in + M.pure Constant.None_)). + +Axiom dataset_size_in_globals : + IsInGlobals globals "dataset_size" (make_function dataset_size). + +Definition generate_seed : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Obtain the cache generation seed for the block identified by + `block_number`. See [`generate_cache`]. + + [`generate_cache`]: ref:ethereum.ethash.generate_cache + " in + let _ := M.assign_local (| + "epoch_number" , + M.call (| + M.get_name (| globals, locals_stack, "epoch" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "seed" , + BinOp.mult (| + Constant.bytes "00", + Constant.int 32 + |) + |) in + let _ := + M.while (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "epoch_number" |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "seed" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "seed" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "epoch_number", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "seed" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_seed_in_globals : + IsInGlobals globals "generate_seed" (make_function generate_seed). + +Definition generate_cache : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "seed" , + M.call (| + M.get_name (| globals, locals_stack, "generate_seed" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache_size_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "cache_size" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache_size_words" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "cache_size_bytes" |), + M.get_name (| globals, locals_stack, "HASH_BYTES" |) + |) + |) in + let _ := M.assign_local (| + "cache" , + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak512" |), + make_list [ + M.get_name (| globals, locals_stack, "seed" |) + ], + make_dict [] + |) + ] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "index" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.get_name (| globals, locals_stack, "cache_size_words" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "cache_item" , + M.call (| + M.get_name (| globals, locals_stack, "keccak512" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "cache" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "index" |), + Constant.int 1 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "cache" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "cache_item" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "CACHE_ROUNDS" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "index" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "cache_size_words" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "first_cache_item" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "cache" |), + BinOp.mod_ (| + BinOp.add (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "index" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "cache_size_words" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "cache_size_words" |) + |) + |) + |) in + let _ := M.assign_local (| + "second_cache_item" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "cache" |), + BinOp.mod_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U32" |), "from_le_bytes" |), + make_list [ + M.slice (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "cache" |), + M.get_name (| globals, locals_stack, "index" |) + |), + Constant.int 0, + Constant.int 4, + Constant.None_ + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "cache_size_words" |) + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)" + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "cache" |), + M.get_name (| globals, locals_stack, "index" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak512" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [ + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_cache_in_globals : + IsInGlobals globals "generate_cache" (make_function generate_cache). + +Definition fnv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "result" , + BinOp.bit_and (| + BinOp.bit_xor (| + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |), + Constant.int 16777619 + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "U32" |), "MAX_VALUE" |) + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U32" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom fnv_in_globals : + IsInGlobals globals "fnv" (make_function fnv). + +Definition fnv_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "mix_integers"; "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [ + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom fnv_hash_in_globals : + IsInGlobals globals "fnv_hash" (make_function fnv_hash). + +Definition generate_dataset_item : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cache"; "index" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "mix" , + M.call (| + M.get_name (| globals, locals_stack, "keccak512" |), + make_list [ + M.call (| + M.get_field (| BinOp.bit_xor (| + M.call (| + M.get_name (| globals, locals_stack, "le_uint32_sequence_to_uint" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "cache" |), + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "index" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "cache" |) + ], + make_dict [] + |) + |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "index" |) + |), "to_le_bytes" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "mix_integers" , + M.call (| + M.get_name (| globals, locals_stack, "le_bytes_to_uint32_sequence" |), + make_list [ + M.get_name (| globals, locals_stack, "mix" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "DATASET_PARENTS" |) + ], + make_dict [] + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "cache_index" , + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "fnv" |), + make_list [ + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "index" |), + M.get_name (| globals, locals_stack, "j" |) + |); + M.get_name (| globals, locals_stack, "mix_word" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "cache" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "parent" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "cache" |), + M.get_name (| globals, locals_stack, "cache_index" |) + |) + |) in + let _ := M.assign_local (| + "mix_integers" , + M.call (| + M.get_name (| globals, locals_stack, "fnv_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "mix_integers" |); + M.get_name (| globals, locals_stack, "parent" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "mix" , + M.call (| + M.get_name (| globals, locals_stack, "Hash64" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "le_uint32_sequence_to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "mix_integers" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak512" |), + make_list [ + M.get_name (| globals, locals_stack, "mix" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_dataset_item_in_globals : + IsInGlobals globals "generate_dataset_item" (make_function generate_dataset_item). + +Definition generate_dataset : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [ + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_dataset_in_globals : + IsInGlobals globals "generate_dataset" (make_function generate_dataset). + +Definition hashimoto : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header_hash"; "nonce"; "dataset_size"; "fetch_dataset_item" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "nonce_le" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "reversed" |), + make_list [ + M.get_name (| globals, locals_stack, "nonce" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "seed_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak512" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "header_hash" |), + M.get_name (| globals, locals_stack, "nonce_le" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "seed_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U32" |), "from_le_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "seed_hash" |), + Constant.None_, + Constant.int 4, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "rows" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dataset_size" |), + Constant.int 128 + |) + |) in + let _ := M.assign_local (| + "mix" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "le_bytes_to_uint32_sequence" |), + make_list [ + M.get_name (| globals, locals_stack, "seed_hash" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "MIX_BYTES" |), + M.get_name (| globals, locals_stack, "HASH_BYTES" |) + |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "HASHIMOTO_ACCESSES" |) + ], + make_dict [] + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "parent" , + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "fnv" |), + make_list [ + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "seed_head" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "mix" |), + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "mix" |) + ], + make_dict [] + |) + |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "rows" |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "MIX_BYTES" |), + M.get_name (| globals, locals_stack, "HASH_BYTES" |) + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "new_data", + M.call (| + M.get_name (| globals, locals_stack, "fetch_dataset_item" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "parent" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "j" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "mix" , + M.call (| + M.get_name (| globals, locals_stack, "fnv_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "mix" |); + M.get_name (| globals, locals_stack, "new_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "compressed_mix" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "mix" |) + ], + make_dict [] + |); + Constant.int 4 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compressed_mix" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "fnv" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "fnv" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "fnv" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "mix" |), + M.get_name (| globals, locals_stack, "i" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "mix" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + ], + make_dict [] + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "mix" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 2 + |) + |) + ], + make_dict [] + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "mix" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 3 + |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "mix_digest" , + M.call (| + M.get_name (| globals, locals_stack, "le_uint32_sequence_to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compressed_mix" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "seed_hash" |), + M.get_name (| globals, locals_stack, "mix_digest" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ] + |) in + M.pure Constant.None_)). + +Axiom hashimoto_in_globals : + IsInGlobals globals "hashimoto" (make_function hashimoto). + +Definition hashimoto_light : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header_hash"; "nonce"; "cache"; "dataset_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "hashimoto" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_name (| globals, locals_stack, "nonce" |); + M.get_name (| globals, locals_stack, "dataset_size" |); + M.get_name (| globals, locals_stack, "fetch_dataset_item" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hashimoto_light_in_globals : + IsInGlobals globals "hashimoto_light" (make_function hashimoto_light). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/exceptions.md new file mode 100644 index 00000000..ceb82cf2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/exceptions.md @@ -0,0 +1,66 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/./exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Exceptions +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The Ethereum specification exception classes. +". + +Definition EthereumException : Value.t := make_klass {| + Klass.bases := [ + (globals, "Exception") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidBlock : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition RLPDecodingError : Value.t := make_klass {| + Klass.bases := [ + (globals, "InvalidBlock") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition RLPEncodingError : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/fork_criteria.md b/docs/revm-python-spec/revm-verif/spec-coq/fork_criteria.md new file mode 100644 index 00000000..4ea31780 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/fork_criteria.md @@ -0,0 +1,297 @@ +# ๐Ÿ“ fork_criteria.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/./fork_criteria.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.fork_criteria". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Fork Criteria +^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Classes for specifying criteria for Mainnet forks. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom abc_imports_ABC : + IsImported globals "abc" "ABC". +Axiom abc_imports_abstractmethod : + IsImported globals "abc" "abstractmethod". + +Axiom typing_imports_Final : + IsImported globals "typing" "Final". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Definition ForkCriteria : Value.t := make_klass {| + Klass.bases := [ + (globals, "ABC") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__eq__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "other" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Equality for fork criteria. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "other" |); + M.get_name (| globals, locals_stack, "ForkCriteria" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "_internal" |), + M.get_field (| M.get_name (| globals, locals_stack, "other" |), "_internal" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_)) + ); + ( + "__lt__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "other" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Ordering for fork criteria. Block number forks are before timestamp + forks and scheduled forks are before unscheduled forks. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "other" |); + M.get_name (| globals, locals_stack, "ForkCriteria" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "_internal" |), + M.get_field (| M.get_name (| globals, locals_stack, "other" |), "_internal" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "NotImplemented" |) + |) in + M.pure Constant.None_)) + ); + ( + "__hash__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + `ForkCriteria` is hashable, so it can be stored in dictionaries. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "hash" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "_internal" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition ByBlockNumber : Value.t := make_klass {| + Klass.bases := [ + (globals, "ForkCriteria") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "block_number" ] in + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "_internal" |), + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "ForkCriteria" |), "BLOCK_NUMBER" |); M.get_name (| globals, locals_stack, "block_number" |) ] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "block_number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) in + M.pure Constant.None_)) + ); + ( + "check", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "block_number"; "timestamp" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Check whether the block number has been reached. + " in + let _ := M.return_ (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "block_number" |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "__repr__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + String representation of this object. + " in + let _ := M.return_ (| + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition ByTimestamp : Value.t := make_klass {| + Klass.bases := [ + (globals, "ForkCriteria") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "timestamp" ] in + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "_internal" |), + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "ForkCriteria" |), "TIMESTAMP" |); M.get_name (| globals, locals_stack, "timestamp" |) ] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "timestamp" |), + M.get_name (| globals, locals_stack, "timestamp" |) + |) in + M.pure Constant.None_)) + ); + ( + "check", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "block_number"; "timestamp" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Check whether the timestamp has been reached. + " in + let _ := M.return_ (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "timestamp" |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "__repr__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + String representation of this object. + " in + let _ := M.return_ (| + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition Unscheduled : Value.t := make_klass {| + Klass.bases := [ + (globals, "ForkCriteria") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "_internal" |), + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "ForkCriteria" |), "UNSCHEDULED" |); Constant.int 0 ] + |) in + M.pure Constant.None_)) + ); + ( + "check", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "block_number"; "timestamp" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Unscheduled forks never occur. + " in + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_)) + ); + ( + "__repr__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self" ] in + ltac:(M.monadic ( + let _ := Constant.str " + String representation of this object. + " in + let _ := M.return_ (| + Constant.str "Unscheduled()" + |) in + M.pure Constant.None_)) + ) + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/__init__.md new file mode 100644 index 00000000..29754acf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/__init__.md @@ -0,0 +1,29 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Frontier is the first production-ready iteration of the Ethereum protocol. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/blocks.md new file mode 100644 index 00000000..b23ae650 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/blocks.md @@ -0,0 +1,91 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Bloom : + IsImported globals "ethereum.frontier.fork_types" "Bloom". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". + +Axiom ethereum_frontier_transactions_imports_Transaction : + IsImported globals "ethereum.frontier.transactions" "Transaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/bloom.md new file mode 100644 index 00000000..189cd73b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". + +Axiom ethereum_frontier_fork_types_imports_Bloom : + IsImported globals "ethereum.frontier.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/fork.md new file mode 100644 index 00000000..9d0eedb5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/fork.md @@ -0,0 +1,2571 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_imports_vm : + IsImported globals "ethereum.frontier" "vm". + +Axiom ethereum_frontier_blocks_imports_Block : + IsImported globals "ethereum.frontier.blocks" "Block". +Axiom ethereum_frontier_blocks_imports_Header : + IsImported globals "ethereum.frontier.blocks" "Header". +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". +Axiom ethereum_frontier_blocks_imports_Receipt : + IsImported globals "ethereum.frontier.blocks" "Receipt". + +Axiom ethereum_frontier_bloom_imports_logs_bloom : + IsImported globals "ethereum.frontier.bloom" "logs_bloom". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Bloom : + IsImported globals "ethereum.frontier.fork_types" "Bloom". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". + +Axiom ethereum_frontier_state_imports_State : + IsImported globals "ethereum.frontier.state" "State". +Axiom ethereum_frontier_state_imports_create_ether : + IsImported globals "ethereum.frontier.state" "create_ether". +Axiom ethereum_frontier_state_imports_destroy_account : + IsImported globals "ethereum.frontier.state" "destroy_account". +Axiom ethereum_frontier_state_imports_get_account : + IsImported globals "ethereum.frontier.state" "get_account". +Axiom ethereum_frontier_state_imports_increment_nonce : + IsImported globals "ethereum.frontier.state" "increment_nonce". +Axiom ethereum_frontier_state_imports_set_account_balance : + IsImported globals "ethereum.frontier.state" "set_account_balance". +Axiom ethereum_frontier_state_imports_state_root : + IsImported globals "ethereum.frontier.state" "state_root". + +Axiom ethereum_frontier_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.frontier.transactions" "TX_BASE_COST". +Axiom ethereum_frontier_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.frontier.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_frontier_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.frontier.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_frontier_transactions_imports_Transaction : + IsImported globals "ethereum.frontier.transactions" "Transaction". + +Axiom ethereum_frontier_trie_imports_Trie : + IsImported globals "ethereum.frontier.trie" "Trie". +Axiom ethereum_frontier_trie_imports_root : + IsImported globals "ethereum.frontier.trie" "root". +Axiom ethereum_frontier_trie_imports_trie_set : + IsImported globals "ethereum.frontier.trie" "trie_set". + +Axiom ethereum_frontier_utils_message_imports_prepare_message : + IsImported globals "ethereum.frontier.utils.message" "prepare_message". + +Axiom ethereum_frontier_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.frontier.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "v" |); M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_in_globals : + IsInGlobals globals "signing_hash" (make_function signing_hash). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_difficulty" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2048 + ], + make_dict [] + |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_timestamp" |), + Constant.int 13 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_difficulty" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "difficulty" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_difficulty" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/fork_types.md new file mode 100644 index 00000000..0faf1641 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/state.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/state.md new file mode 100644 index 00000000..74be7b6d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/state.md @@ -0,0 +1,998 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_frontier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.frontier.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_frontier_fork_types_imports_Account : + IsImported globals "ethereum.frontier.fork_types" "Account". +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". + +Axiom ethereum_frontier_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.frontier.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_frontier_trie_imports_Trie : + IsImported globals "ethereum.frontier.trie" "Trie". +Axiom ethereum_frontier_trie_imports_copy_trie : + IsImported globals "ethereum.frontier.trie" "copy_trie". +Axiom ethereum_frontier_trie_imports_root : + IsImported globals "ethereum.frontier.trie" "root". +Axiom ethereum_frontier_trie_imports_trie_get : + IsImported globals "ethereum.frontier.trie" "trie_get". +Axiom ethereum_frontier_trie_imports_trie_set : + IsImported globals "ethereum.frontier.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/transactions.md new file mode 100644 index 00000000..ce429c5c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/transactions.md @@ -0,0 +1,59 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition Transaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/trie.md new file mode 100644 index 00000000..b542c6c5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/trie.md @@ -0,0 +1,1633 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_frontier_blocks_imports_Receipt : + IsImported globals "ethereum.frontier.blocks" "Receipt". + +Axiom ethereum_frontier_fork_types_imports_Account : + IsImported globals "ethereum.frontier.fork_types" "Account". +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". +Axiom ethereum_frontier_fork_types_imports_encode_account : + IsImported globals "ethereum.frontier.fork_types" "encode_account". + +Axiom ethereum_frontier_transactions_imports_Transaction : + IsImported globals "ethereum.frontier.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Receipt" |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/__init__.md new file mode 100644 index 00000000..aad9e363 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/address.md new file mode 100644 index 00000000..a52b1ac3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/address.md @@ -0,0 +1,159 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this frontier version of specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/hexadecimal.md new file mode 100644 index 00000000..f06721f8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Frontier +types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Bloom : + IsImported globals "ethereum.frontier.fork_types" "Bloom". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/message.md new file mode 100644 index 00000000..1127a3f3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/utils/message.md @@ -0,0 +1,218 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_get_account : + IsImported globals "ethereum.frontier.state" "get_account". + +Axiom ethereum_frontier_vm_imports_Environment : + IsImported globals "ethereum.frontier.vm" "Environment". +Axiom ethereum_frontier_vm_imports_Message : + IsImported globals "ethereum.frontier.vm" "Message". + +Axiom ethereum_frontier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.frontier.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/__init__.md new file mode 100644 index 00000000..03132114 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/__init__.md @@ -0,0 +1,158 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_State : + IsImported globals "ethereum.frontier.state" "State". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/exceptions.md new file mode 100644 index 00000000..225c4d13 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/exceptions.md @@ -0,0 +1,131 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/gas.md new file mode 100644 index 00000000..1b757d86 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/gas.md @@ -0,0 +1,874 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_State : + IsImported globals "ethereum.frontier.state" "State". +Axiom ethereum_frontier_state_imports_account_exists : + IsImported globals "ethereum.frontier.state" "account_exists". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.frontier.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 40 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "gas"; "to"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "gas" |) + |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + |) in + let _ := M.assign_local (| + "stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "gas" |) + (* else *) + )), ltac:(M.monadic ( +BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |), + M.get_name (| globals, locals_stack, "gas" |) + |) + )) |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + M.get_name (| globals, locals_stack, "cost" |); + M.get_name (| globals, locals_stack, "stipend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/__init__.md new file mode 100644 index 00000000..77236b51 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_frontier_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.frontier.vm.instructions" "arithmetic". + +Axiom ethereum_frontier_vm_instructions_imports_bitwise : + IsImported globals "ethereum.frontier.vm.instructions" "bitwise". + +Axiom ethereum_frontier_vm_instructions_imports_block : + IsImported globals "ethereum.frontier.vm.instructions" "block". + +Axiom ethereum_frontier_vm_instructions_imports_comparison : + IsImported globals "ethereum.frontier.vm.instructions" "comparison". + +Axiom ethereum_frontier_vm_instructions_imports_control_flow : + IsImported globals "ethereum.frontier.vm.instructions" "control_flow". + +Axiom ethereum_frontier_vm_instructions_imports_environment : + IsImported globals "ethereum.frontier.vm.instructions" "environment". + +Axiom ethereum_frontier_vm_instructions_imports_keccak : + IsImported globals "ethereum.frontier.vm.instructions" "keccak". + +Axiom ethereum_frontier_vm_instructions_imports_log : + IsImported globals "ethereum.frontier.vm.instructions" "log". + +Axiom ethereum_frontier_vm_instructions_imports_memory : + IsImported globals "ethereum.frontier.vm.instructions" "memory". + +Axiom ethereum_frontier_vm_instructions_imports_stack : + IsImported globals "ethereum.frontier.vm.instructions" "stack". + +Axiom ethereum_frontier_vm_instructions_imports_storage : + IsImported globals "ethereum.frontier.vm.instructions" "storage". + +Axiom ethereum_frontier_vm_instructions_imports_system : + IsImported globals "ethereum.frontier.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/arithmetic.md new file mode 100644 index 00000000..46d784d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.frontier.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_frontier_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_frontier_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_LOW". +Axiom ethereum_frontier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.frontier.vm.gas" "GAS_MID". +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/bitwise.md new file mode 100644 index 00000000..adf8f891 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/bitwise.md @@ -0,0 +1,400 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/block.md new file mode 100644 index 00000000..280ce10e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/block.md @@ -0,0 +1,380 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/comparison.md new file mode 100644 index 00000000..1dad7ca5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/control_flow.md new file mode 100644 index 00000000..13b967cc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.frontier.vm.gas" "GAS_HIGH". +Axiom ethereum_frontier_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.frontier.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_frontier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.frontier.vm.gas" "GAS_MID". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.frontier.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/environment.md new file mode 100644 index 00000000..96604c18 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/environment.md @@ -0,0 +1,1053 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_state_imports_get_account : + IsImported globals "ethereum.frontier.state" "get_account". + +Axiom ethereum_frontier_utils_address_imports_to_address : + IsImported globals "ethereum.frontier.utils.address" "to_address". + +Axiom ethereum_frontier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.frontier.vm.memory" "buffer_read". +Axiom ethereum_frontier_vm_memory_imports_memory_write : + IsImported globals "ethereum.frontier.vm.memory" "memory_write". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BALANCE". +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.frontier.vm.gas" "GAS_COPY". +Axiom ethereum_frontier_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.frontier.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/keccak.md new file mode 100644 index 00000000..065bffd1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.frontier.vm.gas" "GAS_KECCAK256". +Axiom ethereum_frontier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.frontier.vm.memory" "memory_read_bytes". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/log.md new file mode 100644 index 00000000..ab6770d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/log.md @@ -0,0 +1,254 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.frontier.vm.gas" "GAS_LOG". +Axiom ethereum_frontier_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.frontier.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_frontier_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.frontier.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.frontier.vm.memory" "memory_read_bytes". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/memory.md new file mode 100644 index 00000000..5112e45d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.frontier.vm.memory" "memory_read_bytes". +Axiom ethereum_frontier_vm_memory_imports_memory_write : + IsImported globals "ethereum.frontier.vm.memory" "memory_write". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/stack.md new file mode 100644 index 00000000..a0a413c8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". +Axiom ethereum_frontier_vm_imports_stack : + IsImported globals "ethereum.frontier.vm" "stack". + +Axiom ethereum_frontier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.frontier.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.frontier.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/storage.md new file mode 100644 index 00000000..a914edf2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/storage.md @@ -0,0 +1,250 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_frontier_state_imports_get_storage : + IsImported globals "ethereum.frontier.state" "get_storage". +Axiom ethereum_frontier_state_imports_set_storage : + IsImported globals "ethereum.frontier.state" "set_storage". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_SLOAD". +Axiom ethereum_frontier_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.frontier.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_frontier_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.frontier.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_frontier_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/system.md new file mode 100644 index 00000000..27287730 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/instructions/system.md @@ -0,0 +1,1269 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.frontier.state" "account_has_code_or_nonce". +Axiom ethereum_frontier_state_imports_get_account : + IsImported globals "ethereum.frontier.state" "get_account". +Axiom ethereum_frontier_state_imports_increment_nonce : + IsImported globals "ethereum.frontier.state" "increment_nonce". +Axiom ethereum_frontier_state_imports_set_account_balance : + IsImported globals "ethereum.frontier.state" "set_account_balance". + +Axiom ethereum_frontier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.frontier.utils.address" "compute_contract_address". +Axiom ethereum_frontier_utils_address_imports_to_address : + IsImported globals "ethereum.frontier.utils.address" "to_address". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". +Axiom ethereum_frontier_vm_imports_Message : + IsImported globals "ethereum.frontier.vm" "Message". +Axiom ethereum_frontier_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.frontier.vm" "incorporate_child_on_error". +Axiom ethereum_frontier_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.frontier.vm" "incorporate_child_on_success". + +Axiom ethereum_frontier_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_CREATE". +Axiom ethereum_frontier_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.frontier.vm.gas" "GAS_ZERO". +Axiom ethereum_frontier_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.frontier.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.frontier.vm.gas" "calculate_message_call_gas". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.frontier.vm.memory" "memory_read_bytes". +Axiom ethereum_frontier_vm_memory_imports_memory_write : + IsImported globals "ethereum.frontier.vm.memory" "memory_write". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_ZERO" |) + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/interpreter.md new file mode 100644 index 00000000..4c8ffed9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/interpreter.md @@ -0,0 +1,603 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.frontier.state" "account_has_code_or_nonce". +Axiom ethereum_frontier_state_imports_begin_transaction : + IsImported globals "ethereum.frontier.state" "begin_transaction". +Axiom ethereum_frontier_state_imports_commit_transaction : + IsImported globals "ethereum.frontier.state" "commit_transaction". +Axiom ethereum_frontier_state_imports_destroy_storage : + IsImported globals "ethereum.frontier.state" "destroy_storage". +Axiom ethereum_frontier_state_imports_move_ether : + IsImported globals "ethereum.frontier.state" "move_ether". +Axiom ethereum_frontier_state_imports_rollback_transaction : + IsImported globals "ethereum.frontier.state" "rollback_transaction". +Axiom ethereum_frontier_state_imports_set_code : + IsImported globals "ethereum.frontier.state" "set_code". +Axiom ethereum_frontier_state_imports_touch_account : + IsImported globals "ethereum.frontier.state" "touch_account". + +Axiom ethereum_frontier_vm_imports_Message : + IsImported globals "ethereum.frontier.vm" "Message". + +Axiom ethereum_frontier_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.frontier.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_frontier_vm_imports_Environment : + IsImported globals "ethereum.frontier.vm" "Environment". +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.frontier.vm.exceptions" "AddressCollision". +Axiom ethereum_frontier_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.frontier.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_frontier_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.frontier.vm.exceptions" "InvalidOpcode". +Axiom ethereum_frontier_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.frontier.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_frontier_vm_instructions_imports_Ops : + IsImported globals "ethereum.frontier.vm.instructions" "Ops". +Axiom ethereum_frontier_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.frontier.vm.instructions" "op_implementation". + +Axiom ethereum_frontier_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.frontier.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/memory.md new file mode 100644 index 00000000..0b90ec65 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..c429a711 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/__init__.md @@ -0,0 +1,74 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_frontier_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.frontier.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..5e07e401 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.frontier.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.frontier.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..fd00e3e9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.frontier.vm.gas" "GAS_IDENTITY". +Axiom ethereum_frontier_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..be0371b5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/mapping.md @@ -0,0 +1,57 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_frontier_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_frontier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_frontier_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_frontier_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_frontier_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_frontier_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_frontier_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..f896a565 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.frontier.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_frontier_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..642012c6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.frontier.vm.gas" "GAS_SHA256". +Axiom ethereum_frontier_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/runtime.md new file mode 100644 index 00000000..47968c20 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_vm_instructions_imports_Ops : + IsImported globals "ethereum.frontier.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/stack.md new file mode 100644 index 00000000..d6595c56 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/frontier/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/frontier/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.frontier.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.frontier.vm.exceptions" "StackOverflowError". +Axiom ethereum_frontier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.frontier.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/genesis.md b/docs/revm-python-spec/revm-verif/spec-coq/genesis.md new file mode 100644 index 00000000..d72eb6a7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/genesis.md @@ -0,0 +1,500 @@ +# ๐Ÿ“ genesis.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/./genesis.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.genesis". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Genesis Configuration +^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Functionalities and entities to obtain the genesis configurations for +different chains. +". + +(* At top_level_stmt: unsupported node type: Import *) + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Any : + IsImported globals "typing" "Any". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes8 : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes8". +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes32 : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes32". +Axiom ethereum_utils_hexadecimal_imports_hex_to_u256 : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_u256". +Axiom ethereum_utils_hexadecimal_imports_hex_to_uint : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_uint". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition GenesisConfiguration : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition get_genesis_configuration : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "genesis_file" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Obtain the genesis configuration from the given genesis json file. + + The genesis file should be present in the `assets` directory. + + Parameters + ---------- + genesis_file : + The json file which contains the parameters for the genesis block + and the pre-sale allocation data. + + Returns + ------- + configuration : `GenesisConfiguration` + The genesis configuration obtained from the json genesis file. + " in + let _ := M.assign_local (| + "genesis_str_data" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "pkgutil" |), "get_data" |), + make_list [ + Constant.str "ethereum"; + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |) + ], + make_dict [] + |), "decode" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "genesis_data" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "json" |), "loads" |), + make_list [ + M.get_name (| globals, locals_stack, "genesis_str_data" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "GenesisConfiguration" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom get_genesis_configuration_in_globals : + IsInGlobals globals "get_genesis_configuration" (make_function get_genesis_configuration). + +Definition hex_or_base_10_str_to_u256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "balance" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The genesis format can have balances and timestamps as either base 10 + numbers or 0x prefixed hex. This function supports both. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "balance" |), "startswith" |), + make_list [ + Constant.str "0x" + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "hex_to_u256" |), + make_list [ + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom hex_or_base_10_str_to_u256_in_globals : + IsInGlobals globals "hex_or_base_10_str_to_u256" (make_function hex_or_base_10_str_to_u256). + +Definition add_genesis_block : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hardfork"; "chain"; "genesis" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 https://github.com/ethereum/genesis_block_generator. + + 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 edgecases around precompiles being created or + cleared (by EIP 161). + + Parameters + ---------- + hardfork: + The module containing the initial hardfork + chain : + An empty `Blockchain` object. + genesis : + The genesis configuration to use. + " in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "account" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "genesis" |), "initial_accounts" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "address" , + M.call (| + M.get_field (| M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "utils" |), "hexadecimal" |), "hex_to_address" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "state" |), "set_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "fork_types" |), "Account" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "get" |), + make_list [ + Constant.str "nonce"; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "hex_or_base_10_str_to_u256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "get" |), + make_list [ + Constant.str "balance"; + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "get" |), + make_list [ + Constant.str "code"; + Constant.str "0x" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "key" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "get" |), + make_list [ + Constant.str "storage"; + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "state" |), "set_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes32" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "hex_to_uint" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "fields" , + Constant.str "(* At expr: unsupported node type: Dict *)" + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "hasattr" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "blocks" |), "Header" |); + Constant.str "mix_digest" + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "fields" |), + Constant.str "mix_digest" + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "fork_types" |), "Hash32" |), + make_list [ + BinOp.mult (| + Constant.bytes "00", + Constant.int 32 + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "fields" |), + Constant.str "prev_randao" + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "fork_types" |), "Hash32" |), + make_list [ + BinOp.mult (| + Constant.bytes "00", + Constant.int 32 + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "hasattr" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "blocks" |), "Header" |); + Constant.str "base_fee_per_gas" + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "fields" |), + Constant.str "base_fee_per_gas" + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.pow (| + Constant.int 10, + Constant.int 9 + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "genesis_header" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "blocks" |), "Header" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "genesis_block" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "hardfork" |), "blocks" |), "Block" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "genesis_block" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |), + M.get_field (| M.get_name (| globals, locals_stack, "genesis" |), "chain_id" |) + |) in + M.pure Constant.None_)). + +Axiom add_genesis_block_in_globals : + IsInGlobals globals "add_genesis_block" (make_function add_genesis_block). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/__init__.md new file mode 100644 index 00000000..3dedc3b9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/__init__.md @@ -0,0 +1,30 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +The Gray Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 15050000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/blocks.md new file mode 100644 index 00000000..7e3288fd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/blocks.md @@ -0,0 +1,93 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.gray_glacier.fork_types" "Bloom". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". + +Axiom ethereum_gray_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "LegacyTransaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/bloom.md new file mode 100644 index 00000000..b94dd778 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". + +Axiom ethereum_gray_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.gray_glacier.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/fork.md new file mode 100644 index 00000000..d43dbfaa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/fork.md @@ -0,0 +1,3592 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_imports_vm : + IsImported globals "ethereum.gray_glacier" "vm". + +Axiom ethereum_gray_glacier_blocks_imports_Block : + IsImported globals "ethereum.gray_glacier.blocks" "Block". +Axiom ethereum_gray_glacier_blocks_imports_Header : + IsImported globals "ethereum.gray_glacier.blocks" "Header". +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". +Axiom ethereum_gray_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.gray_glacier.blocks" "Receipt". + +Axiom ethereum_gray_glacier_bloom_imports_logs_bloom : + IsImported globals "ethereum.gray_glacier.bloom" "logs_bloom". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.gray_glacier.fork_types" "Bloom". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". + +Axiom ethereum_gray_glacier_state_imports_State : + IsImported globals "ethereum.gray_glacier.state" "State". +Axiom ethereum_gray_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.gray_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_gray_glacier_state_imports_create_ether : + IsImported globals "ethereum.gray_glacier.state" "create_ether". +Axiom ethereum_gray_glacier_state_imports_destroy_account : + IsImported globals "ethereum.gray_glacier.state" "destroy_account". +Axiom ethereum_gray_glacier_state_imports_get_account : + IsImported globals "ethereum.gray_glacier.state" "get_account". +Axiom ethereum_gray_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.gray_glacier.state" "increment_nonce". +Axiom ethereum_gray_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.gray_glacier.state" "set_account_balance". +Axiom ethereum_gray_glacier_state_imports_state_root : + IsImported globals "ethereum.gray_glacier.state" "state_root". + +Axiom ethereum_gray_glacier_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.gray_glacier.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_gray_glacier_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.gray_glacier.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_gray_glacier_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.gray_glacier.transactions" "TX_BASE_COST". +Axiom ethereum_gray_glacier_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.gray_glacier.transactions" "TX_CREATE_COST". +Axiom ethereum_gray_glacier_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.gray_glacier.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_gray_glacier_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.gray_glacier.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_gray_glacier_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "AccessListTransaction". +Axiom ethereum_gray_glacier_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "FeeMarketTransaction". +Axiom ethereum_gray_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "LegacyTransaction". +Axiom ethereum_gray_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.gray_glacier.transactions" "Transaction". +Axiom ethereum_gray_glacier_transactions_imports_decode_transaction : + IsImported globals "ethereum.gray_glacier.transactions" "decode_transaction". +Axiom ethereum_gray_glacier_transactions_imports_encode_transaction : + IsImported globals "ethereum.gray_glacier.transactions" "encode_transaction". + +Axiom ethereum_gray_glacier_trie_imports_Trie : + IsImported globals "ethereum.gray_glacier.trie" "Trie". +Axiom ethereum_gray_glacier_trie_imports_root : + IsImported globals "ethereum.gray_glacier.trie" "root". +Axiom ethereum_gray_glacier_trie_imports_trie_set : + IsImported globals "ethereum.gray_glacier.trie" "trie_set". + +Axiom ethereum_gray_glacier_utils_message_imports_prepare_message : + IsImported globals "ethereum.gray_glacier.utils.message" "prepare_message". + +Axiom ethereum_gray_glacier_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.gray_glacier.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 11400000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_limit" |); + M.get_name (| globals, locals_stack, "parent_gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_target" |), + M.get_name (| globals, locals_stack, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_base_fee_per_gas_in_globals : + IsInGlobals globals "calculate_base_fee_per_gas" (make_function calculate_base_fee_per_gas). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |); + M.get_name (| globals, locals_stack, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "base_fee_per_gas" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "map" |), + make_list [ + M.get_name (| globals, locals_stack, "decode_transaction" |); + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "encode_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "base_fee_per_gas" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "_address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |), + M.get_name (| globals, locals_stack, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_2930_in_globals : + IsInGlobals globals "signing_hash_2930" (make_function signing_hash_2930). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_1559_in_globals : + IsInGlobals globals "signing_hash_1559" (make_function signing_hash_1559). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/fork_types.md new file mode 100644 index 00000000..47e7854d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/state.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/state.md new file mode 100644 index 00000000..98233b81 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/state.md @@ -0,0 +1,1391 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_gray_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.gray_glacier.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_gray_glacier_fork_types_imports_Account : + IsImported globals "ethereum.gray_glacier.fork_types" "Account". +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". + +Axiom ethereum_gray_glacier_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.gray_glacier.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_gray_glacier_trie_imports_Trie : + IsImported globals "ethereum.gray_glacier.trie" "Trie". +Axiom ethereum_gray_glacier_trie_imports_copy_trie : + IsImported globals "ethereum.gray_glacier.trie" "copy_trie". +Axiom ethereum_gray_glacier_trie_imports_root : + IsImported globals "ethereum.gray_glacier.trie" "root". +Axiom ethereum_gray_glacier_trie_imports_trie_get : + IsImported globals "ethereum.gray_glacier.trie" "trie_get". +Axiom ethereum_gray_glacier_trie_imports_trie_set : + IsImported globals "ethereum.gray_glacier.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom mark_account_created_in_globals : + IsInGlobals globals "mark_account_created" (make_function mark_account_created). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "_" |); M.get_name (| globals, locals_stack, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "original_account_trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "original_value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "original_value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_original_in_globals : + IsInGlobals globals "get_storage_original" (make_function get_storage_original). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/transactions.md new file mode 100644 index 00000000..901d767c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/transactions.md @@ -0,0 +1,306 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AccessListTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition FeeMarketTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_transaction_in_globals : + IsInGlobals globals "encode_transaction" (make_function encode_transaction). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom decode_transaction_in_globals : + IsInGlobals globals "decode_transaction" (make_function decode_transaction). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/trie.md new file mode 100644 index 00000000..3d925f9f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/trie.md @@ -0,0 +1,1645 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_arrow_glacier_imports_trie : + IsImported globals "ethereum.arrow_glacier" "trie". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_gray_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.gray_glacier.blocks" "Receipt". + +Axiom ethereum_gray_glacier_fork_types_imports_Account : + IsImported globals "ethereum.gray_glacier.fork_types" "Account". +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". +Axiom ethereum_gray_glacier_fork_types_imports_encode_account : + IsImported globals "ethereum.gray_glacier.fork_types" "encode_account". + +Axiom ethereum_gray_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/__init__.md new file mode 100644 index 00000000..410cf6b7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/address.md new file mode 100644 index 00000000..ce01170b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this gray_glacier version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/hexadecimal.md new file mode 100644 index 00000000..6d79132c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.gray_glacier.fork_types" "Bloom". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/message.md new file mode 100644 index 00000000..3554ec4d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/utils/message.md @@ -0,0 +1,278 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_state_imports_get_account : + IsImported globals "ethereum.gray_glacier.state" "get_account". + +Axiom ethereum_gray_glacier_vm_imports_Environment : + IsImported globals "ethereum.gray_glacier.vm" "Environment". +Axiom ethereum_gray_glacier_vm_imports_Message : + IsImported globals "ethereum.gray_glacier.vm" "Message". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_gray_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.gray_glacier.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, locals_stack, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/__init__.md new file mode 100644 index 00000000..7594d9c3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/__init__.md @@ -0,0 +1,273 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_state_imports_State : + IsImported globals "ethereum.gray_glacier.state" "State". +Axiom ethereum_gray_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.gray_glacier.state" "account_exists_and_is_empty". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/exceptions.md new file mode 100644 index 00000000..39cd06e4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/exceptions.md @@ -0,0 +1,181 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidParameter : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidContractPrefix : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/gas.md new file mode 100644 index 00000000..b785fa86 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/gas.md @@ -0,0 +1,938 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/__init__.md new file mode 100644 index 00000000..3e4ac7d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_gray_glacier_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.gray_glacier.vm.instructions" "arithmetic". + +Axiom ethereum_gray_glacier_vm_instructions_imports_bitwise : + IsImported globals "ethereum.gray_glacier.vm.instructions" "bitwise". + +Axiom ethereum_gray_glacier_vm_instructions_imports_block : + IsImported globals "ethereum.gray_glacier.vm.instructions" "block". + +Axiom ethereum_gray_glacier_vm_instructions_imports_comparison : + IsImported globals "ethereum.gray_glacier.vm.instructions" "comparison". + +Axiom ethereum_gray_glacier_vm_instructions_imports_control_flow : + IsImported globals "ethereum.gray_glacier.vm.instructions" "control_flow". + +Axiom ethereum_gray_glacier_vm_instructions_imports_environment : + IsImported globals "ethereum.gray_glacier.vm.instructions" "environment". + +Axiom ethereum_gray_glacier_vm_instructions_imports_keccak : + IsImported globals "ethereum.gray_glacier.vm.instructions" "keccak". + +Axiom ethereum_gray_glacier_vm_instructions_imports_log : + IsImported globals "ethereum.gray_glacier.vm.instructions" "log". + +Axiom ethereum_gray_glacier_vm_instructions_imports_memory : + IsImported globals "ethereum.gray_glacier.vm.instructions" "memory". + +Axiom ethereum_gray_glacier_vm_instructions_imports_stack : + IsImported globals "ethereum.gray_glacier.vm.instructions" "stack". + +Axiom ethereum_gray_glacier_vm_instructions_imports_storage : + IsImported globals "ethereum.gray_glacier.vm.instructions" "storage". + +Axiom ethereum_gray_glacier_vm_instructions_imports_system : + IsImported globals "ethereum.gray_glacier.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/arithmetic.md new file mode 100644 index 00000000..725003d4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_MID". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/bitwise.md new file mode 100644 index 00000000..534f0c63 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/block.md new file mode 100644 index 00000000..af7907bf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/block.md @@ -0,0 +1,426 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom chain_id_in_globals : + IsInGlobals globals "chain_id" (make_function chain_id). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/comparison.md new file mode 100644 index 00000000..e28a2e02 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/control_flow.md new file mode 100644 index 00000000..f12cc981 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_HIGH". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_MID". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/environment.md new file mode 100644 index 00000000..9b460648 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/environment.md @@ -0,0 +1,1610 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.gray_glacier.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_gray_glacier_state_imports_get_account : + IsImported globals "ethereum.gray_glacier.state" "get_account". + +Axiom ethereum_gray_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.gray_glacier.utils.address" "to_address". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". +Axiom ethereum_gray_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_write". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_COPY". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom self_balance_in_globals : + IsInGlobals globals "self_balance" (make_function self_balance). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom base_fee_in_globals : + IsInGlobals globals "base_fee" (make_function base_fee). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/keccak.md new file mode 100644 index 00000000..b81ecb11 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_KECCAK256". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/log.md new file mode 100644 index 00000000..5f4ea10d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_LOG". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/memory.md new file mode 100644 index 00000000..e88c0817 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_gray_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_write". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/stack.md new file mode 100644 index 00000000..a836b5d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". +Axiom ethereum_gray_glacier_vm_imports_stack : + IsImported globals "ethereum.gray_glacier.vm" "stack". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/storage.md new file mode 100644 index 00000000..8d83c223 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/storage.md @@ -0,0 +1,512 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_state_imports_get_storage : + IsImported globals "ethereum.gray_glacier.state" "get_storage". +Axiom ethereum_gray_glacier_state_imports_get_storage_original : + IsImported globals "ethereum.gray_glacier.state" "get_storage_original". +Axiom ethereum_gray_glacier_state_imports_set_storage : + IsImported globals "ethereum.gray_glacier.state" "set_storage". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_gray_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/system.md new file mode 100644 index 00000000..67b8cbe4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/instructions/system.md @@ -0,0 +1,2276 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.gray_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_gray_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.gray_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_gray_glacier_state_imports_get_account : + IsImported globals "ethereum.gray_glacier.state" "get_account". +Axiom ethereum_gray_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.gray_glacier.state" "increment_nonce". +Axiom ethereum_gray_glacier_state_imports_is_account_alive : + IsImported globals "ethereum.gray_glacier.state" "is_account_alive". +Axiom ethereum_gray_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.gray_glacier.state" "set_account_balance". + +Axiom ethereum_gray_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.gray_glacier.utils.address" "compute_contract_address". +Axiom ethereum_gray_glacier_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.gray_glacier.utils.address" "compute_create2_contract_address". +Axiom ethereum_gray_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.gray_glacier.utils.address" "to_address". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". +Axiom ethereum_gray_glacier_vm_imports_Message : + IsImported globals "ethereum.gray_glacier.vm" "Message". +Axiom ethereum_gray_glacier_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.gray_glacier.vm" "incorporate_child_on_error". +Axiom ethereum_gray_glacier_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.gray_glacier.vm" "incorporate_child_on_success". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "Revert". +Axiom ethereum_gray_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_CREATE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_ZERO". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_message_call_gas". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". +Axiom ethereum_gray_glacier_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "max_message_call_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_gray_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_write". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "beneficiary" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/interpreter.md new file mode 100644 index 00000000..ac3518c8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/interpreter.md @@ -0,0 +1,695 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.gray_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_gray_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.gray_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_gray_glacier_state_imports_begin_transaction : + IsImported globals "ethereum.gray_glacier.state" "begin_transaction". +Axiom ethereum_gray_glacier_state_imports_commit_transaction : + IsImported globals "ethereum.gray_glacier.state" "commit_transaction". +Axiom ethereum_gray_glacier_state_imports_destroy_storage : + IsImported globals "ethereum.gray_glacier.state" "destroy_storage". +Axiom ethereum_gray_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.gray_glacier.state" "increment_nonce". +Axiom ethereum_gray_glacier_state_imports_mark_account_created : + IsImported globals "ethereum.gray_glacier.state" "mark_account_created". +Axiom ethereum_gray_glacier_state_imports_move_ether : + IsImported globals "ethereum.gray_glacier.state" "move_ether". +Axiom ethereum_gray_glacier_state_imports_rollback_transaction : + IsImported globals "ethereum.gray_glacier.state" "rollback_transaction". +Axiom ethereum_gray_glacier_state_imports_set_code : + IsImported globals "ethereum.gray_glacier.state" "set_code". +Axiom ethereum_gray_glacier_state_imports_touch_account : + IsImported globals "ethereum.gray_glacier.state" "touch_account". + +Axiom ethereum_gray_glacier_vm_imports_Message : + IsImported globals "ethereum.gray_glacier.vm" "Message". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_gray_glacier_vm_imports_Environment : + IsImported globals "ethereum.gray_glacier.vm" "Environment". +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "AddressCollision". +Axiom ethereum_gray_glacier_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_gray_glacier_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_gray_glacier_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "InvalidOpcode". +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_gray_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "Revert". +Axiom ethereum_gray_glacier_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_gray_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.gray_glacier.vm.instructions" "Ops". +Axiom ethereum_gray_glacier_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.gray_glacier.vm.instructions" "op_implementation". + +Axiom ethereum_gray_glacier_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.gray_glacier.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/memory.md new file mode 100644 index 00000000..f43b7603 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..c4548945 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/__init__.md @@ -0,0 +1,124 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_gray_glacier_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.gray_glacier.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..5b51716e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..9b689c6f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,144 @@ +# ๐Ÿ“ blake2f.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.precompiled_contracts.blake2f". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, locals_stack, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, locals_stack, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, locals_stack, "rounds" |); + M.get_name (| globals, locals_stack, "h" |); + M.get_name (| globals, locals_stack, "m" |); + M.get_name (| globals, locals_stack, "t_0" |); + M.get_name (| globals, locals_stack, "t_1" |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom blake2f_in_globals : + IsInGlobals globals "blake2f" (make_function blake2f). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..c2e193db --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..ccf41367 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_IDENTITY". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..79dbc69d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/mapping.md @@ -0,0 +1,80 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..b8bf9c3a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/modexp.md @@ -0,0 +1,700 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |); + M.get_name (| globals, locals_stack, "exp_length" |); + M.get_name (| globals, locals_stack, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Axiom complexity_in_globals : + IsInGlobals globals "complexity" (make_function complexity). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, locals_stack, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, locals_stack, "length_part" |), + M.get_name (| globals, locals_stack, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "count" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom iterations_in_globals : + IsInGlobals globals "iterations" (make_function iterations). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, locals_stack, "complexity" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, locals_stack, "iterations" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |); + M.get_name (| globals, locals_stack, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "multiplication_complexity" |), + M.get_name (| globals, locals_stack, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom gas_cost_in_globals : + IsInGlobals globals "gas_cost" (make_function gas_cost). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..8ed51108 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..7054981a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_SHA256". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/runtime.md new file mode 100644 index 00000000..8baf73ab --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.gray_glacier.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/stack.md new file mode 100644 index 00000000..c2646e59 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/gray_glacier/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/gray_glacier/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.gray_glacier.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "StackOverflowError". +Axiom ethereum_gray_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/__init__.md new file mode 100644 index 00000000..c3637015 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/__init__.md @@ -0,0 +1,32 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 1150000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/blocks.md new file mode 100644 index 00000000..b03f3cb7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/blocks.md @@ -0,0 +1,91 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Bloom : + IsImported globals "ethereum.homestead.fork_types" "Bloom". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". + +Axiom ethereum_homestead_transactions_imports_Transaction : + IsImported globals "ethereum.homestead.transactions" "Transaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/bloom.md new file mode 100644 index 00000000..7606f361 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". + +Axiom ethereum_homestead_fork_types_imports_Bloom : + IsImported globals "ethereum.homestead.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/fork.md new file mode 100644 index 00000000..8216bd20 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/fork.md @@ -0,0 +1,2630 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_imports_vm : + IsImported globals "ethereum.homestead" "vm". + +Axiom ethereum_homestead_blocks_imports_Block : + IsImported globals "ethereum.homestead.blocks" "Block". +Axiom ethereum_homestead_blocks_imports_Header : + IsImported globals "ethereum.homestead.blocks" "Header". +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". +Axiom ethereum_homestead_blocks_imports_Receipt : + IsImported globals "ethereum.homestead.blocks" "Receipt". + +Axiom ethereum_homestead_bloom_imports_logs_bloom : + IsImported globals "ethereum.homestead.bloom" "logs_bloom". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Bloom : + IsImported globals "ethereum.homestead.fork_types" "Bloom". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". + +Axiom ethereum_homestead_state_imports_State : + IsImported globals "ethereum.homestead.state" "State". +Axiom ethereum_homestead_state_imports_create_ether : + IsImported globals "ethereum.homestead.state" "create_ether". +Axiom ethereum_homestead_state_imports_destroy_account : + IsImported globals "ethereum.homestead.state" "destroy_account". +Axiom ethereum_homestead_state_imports_get_account : + IsImported globals "ethereum.homestead.state" "get_account". +Axiom ethereum_homestead_state_imports_increment_nonce : + IsImported globals "ethereum.homestead.state" "increment_nonce". +Axiom ethereum_homestead_state_imports_set_account_balance : + IsImported globals "ethereum.homestead.state" "set_account_balance". +Axiom ethereum_homestead_state_imports_state_root : + IsImported globals "ethereum.homestead.state" "state_root". + +Axiom ethereum_homestead_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.homestead.transactions" "TX_BASE_COST". +Axiom ethereum_homestead_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.homestead.transactions" "TX_CREATE_COST". +Axiom ethereum_homestead_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.homestead.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_homestead_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.homestead.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_homestead_transactions_imports_Transaction : + IsImported globals "ethereum.homestead.transactions" "Transaction". + +Axiom ethereum_homestead_trie_imports_Trie : + IsImported globals "ethereum.homestead.trie" "Trie". +Axiom ethereum_homestead_trie_imports_root : + IsImported globals "ethereum.homestead.trie" "root". +Axiom ethereum_homestead_trie_imports_trie_set : + IsImported globals "ethereum.homestead.trie" "trie_set". + +Axiom ethereum_homestead_utils_message_imports_prepare_message : + IsImported globals "ethereum.homestead.utils.message" "prepare_message". + +Axiom ethereum_homestead_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.homestead.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "v" |); M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_in_globals : + IsInGlobals globals "signing_hash" (make_function signing_hash). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + Constant.int 1, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 10 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/fork_types.md new file mode 100644 index 00000000..38a490f1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/state.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/state.md new file mode 100644 index 00000000..c566409a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/state.md @@ -0,0 +1,998 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_homestead_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.homestead.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_homestead_fork_types_imports_Account : + IsImported globals "ethereum.homestead.fork_types" "Account". +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". + +Axiom ethereum_homestead_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.homestead.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_homestead_trie_imports_Trie : + IsImported globals "ethereum.homestead.trie" "Trie". +Axiom ethereum_homestead_trie_imports_copy_trie : + IsImported globals "ethereum.homestead.trie" "copy_trie". +Axiom ethereum_homestead_trie_imports_root : + IsImported globals "ethereum.homestead.trie" "root". +Axiom ethereum_homestead_trie_imports_trie_get : + IsImported globals "ethereum.homestead.trie" "trie_get". +Axiom ethereum_homestead_trie_imports_trie_set : + IsImported globals "ethereum.homestead.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/transactions.md new file mode 100644 index 00000000..03ac8c25 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/transactions.md @@ -0,0 +1,63 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/trie.md new file mode 100644 index 00000000..5ee61c6d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/trie.md @@ -0,0 +1,1639 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_frontier_imports_trie : + IsImported globals "ethereum.frontier" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_homestead_blocks_imports_Receipt : + IsImported globals "ethereum.homestead.blocks" "Receipt". + +Axiom ethereum_homestead_fork_types_imports_Account : + IsImported globals "ethereum.homestead.fork_types" "Account". +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". +Axiom ethereum_homestead_fork_types_imports_encode_account : + IsImported globals "ethereum.homestead.fork_types" "encode_account". + +Axiom ethereum_homestead_transactions_imports_Transaction : + IsImported globals "ethereum.homestead.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Receipt" |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/__init__.md new file mode 100644 index 00000000..9a651229 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/address.md new file mode 100644 index 00000000..4881f6a5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/address.md @@ -0,0 +1,159 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this homestead version of specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/hexadecimal.md new file mode 100644 index 00000000..6963bc82 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Homestead +types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Bloom : + IsImported globals "ethereum.homestead.fork_types" "Bloom". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/message.md new file mode 100644 index 00000000..ff5b7247 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/utils/message.md @@ -0,0 +1,220 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_get_account : + IsImported globals "ethereum.homestead.state" "get_account". + +Axiom ethereum_homestead_vm_imports_Environment : + IsImported globals "ethereum.homestead.vm" "Environment". +Axiom ethereum_homestead_vm_imports_Message : + IsImported globals "ethereum.homestead.vm" "Message". + +Axiom ethereum_homestead_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.homestead.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/__init__.md new file mode 100644 index 00000000..79fdd5fd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/__init__.md @@ -0,0 +1,158 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_State : + IsImported globals "ethereum.homestead.state" "State". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/exceptions.md new file mode 100644 index 00000000..33dfe999 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/exceptions.md @@ -0,0 +1,131 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/gas.md new file mode 100644 index 00000000..df18b4f4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/gas.md @@ -0,0 +1,874 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_State : + IsImported globals "ethereum.homestead.state" "State". +Axiom ethereum_homestead_state_imports_account_exists : + IsImported globals "ethereum.homestead.state" "account_exists". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.homestead.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 40 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "gas"; "to"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "gas" |) + |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + |) in + let _ := M.assign_local (| + "stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "gas" |) + (* else *) + )), ltac:(M.monadic ( +BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |), + M.get_name (| globals, locals_stack, "gas" |) + |) + )) |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + M.get_name (| globals, locals_stack, "cost" |); + M.get_name (| globals, locals_stack, "stipend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/__init__.md new file mode 100644 index 00000000..b2c384fe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_homestead_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.homestead.vm.instructions" "arithmetic". + +Axiom ethereum_homestead_vm_instructions_imports_bitwise : + IsImported globals "ethereum.homestead.vm.instructions" "bitwise". + +Axiom ethereum_homestead_vm_instructions_imports_block : + IsImported globals "ethereum.homestead.vm.instructions" "block". + +Axiom ethereum_homestead_vm_instructions_imports_comparison : + IsImported globals "ethereum.homestead.vm.instructions" "comparison". + +Axiom ethereum_homestead_vm_instructions_imports_control_flow : + IsImported globals "ethereum.homestead.vm.instructions" "control_flow". + +Axiom ethereum_homestead_vm_instructions_imports_environment : + IsImported globals "ethereum.homestead.vm.instructions" "environment". + +Axiom ethereum_homestead_vm_instructions_imports_keccak : + IsImported globals "ethereum.homestead.vm.instructions" "keccak". + +Axiom ethereum_homestead_vm_instructions_imports_log : + IsImported globals "ethereum.homestead.vm.instructions" "log". + +Axiom ethereum_homestead_vm_instructions_imports_memory : + IsImported globals "ethereum.homestead.vm.instructions" "memory". + +Axiom ethereum_homestead_vm_instructions_imports_stack : + IsImported globals "ethereum.homestead.vm.instructions" "stack". + +Axiom ethereum_homestead_vm_instructions_imports_storage : + IsImported globals "ethereum.homestead.vm.instructions" "storage". + +Axiom ethereum_homestead_vm_instructions_imports_system : + IsImported globals "ethereum.homestead.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/arithmetic.md new file mode 100644 index 00000000..b6cf0a25 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.homestead.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_homestead_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_homestead_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_LOW". +Axiom ethereum_homestead_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.homestead.vm.gas" "GAS_MID". +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/bitwise.md new file mode 100644 index 00000000..ee8fadc1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/bitwise.md @@ -0,0 +1,400 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/block.md new file mode 100644 index 00000000..7e93889d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/block.md @@ -0,0 +1,380 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/comparison.md new file mode 100644 index 00000000..e654b7e9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/control_flow.md new file mode 100644 index 00000000..3ffe9b07 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.homestead.vm.gas" "GAS_HIGH". +Axiom ethereum_homestead_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.homestead.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_homestead_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.homestead.vm.gas" "GAS_MID". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.homestead.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/environment.md new file mode 100644 index 00000000..c44d1512 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/environment.md @@ -0,0 +1,1053 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_state_imports_get_account : + IsImported globals "ethereum.homestead.state" "get_account". + +Axiom ethereum_homestead_utils_address_imports_to_address : + IsImported globals "ethereum.homestead.utils.address" "to_address". + +Axiom ethereum_homestead_vm_memory_imports_buffer_read : + IsImported globals "ethereum.homestead.vm.memory" "buffer_read". +Axiom ethereum_homestead_vm_memory_imports_memory_write : + IsImported globals "ethereum.homestead.vm.memory" "memory_write". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BALANCE". +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.homestead.vm.gas" "GAS_COPY". +Axiom ethereum_homestead_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.homestead.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/keccak.md new file mode 100644 index 00000000..8f1afc94 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.homestead.vm.gas" "GAS_KECCAK256". +Axiom ethereum_homestead_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.homestead.vm.memory" "memory_read_bytes". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/log.md new file mode 100644 index 00000000..6783a62b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/log.md @@ -0,0 +1,254 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.homestead.vm.gas" "GAS_LOG". +Axiom ethereum_homestead_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.homestead.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_homestead_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.homestead.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.homestead.vm.memory" "memory_read_bytes". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/memory.md new file mode 100644 index 00000000..424f4fbf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.homestead.vm.memory" "memory_read_bytes". +Axiom ethereum_homestead_vm_memory_imports_memory_write : + IsImported globals "ethereum.homestead.vm.memory" "memory_write". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/stack.md new file mode 100644 index 00000000..bead79ae --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". +Axiom ethereum_homestead_vm_imports_stack : + IsImported globals "ethereum.homestead.vm" "stack". + +Axiom ethereum_homestead_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.homestead.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_buffer_read : + IsImported globals "ethereum.homestead.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/storage.md new file mode 100644 index 00000000..1421f4ef --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/storage.md @@ -0,0 +1,250 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_homestead_state_imports_get_storage : + IsImported globals "ethereum.homestead.state" "get_storage". +Axiom ethereum_homestead_state_imports_set_storage : + IsImported globals "ethereum.homestead.state" "set_storage". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_SLOAD". +Axiom ethereum_homestead_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.homestead.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_homestead_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.homestead.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_homestead_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/system.md new file mode 100644 index 00000000..b1b6412e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/instructions/system.md @@ -0,0 +1,1420 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.homestead.state" "account_has_code_or_nonce". +Axiom ethereum_homestead_state_imports_get_account : + IsImported globals "ethereum.homestead.state" "get_account". +Axiom ethereum_homestead_state_imports_increment_nonce : + IsImported globals "ethereum.homestead.state" "increment_nonce". +Axiom ethereum_homestead_state_imports_set_account_balance : + IsImported globals "ethereum.homestead.state" "set_account_balance". + +Axiom ethereum_homestead_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.homestead.utils.address" "compute_contract_address". +Axiom ethereum_homestead_utils_address_imports_to_address : + IsImported globals "ethereum.homestead.utils.address" "to_address". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". +Axiom ethereum_homestead_vm_imports_Message : + IsImported globals "ethereum.homestead.vm" "Message". +Axiom ethereum_homestead_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.homestead.vm" "incorporate_child_on_error". +Axiom ethereum_homestead_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.homestead.vm" "incorporate_child_on_success". + +Axiom ethereum_homestead_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.homestead.vm.gas" "GAS_CALL". +Axiom ethereum_homestead_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_CREATE". +Axiom ethereum_homestead_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.homestead.vm.gas" "GAS_ZERO". +Axiom ethereum_homestead_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.homestead.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.homestead.vm.gas" "calculate_message_call_gas". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.homestead.vm.memory" "memory_read_bytes". +Axiom ethereum_homestead_vm_memory_imports_memory_write : + IsImported globals "ethereum.homestead.vm.memory" "memory_write". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_ZERO" |) + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "gas" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/interpreter.md new file mode 100644 index 00000000..e19aa198 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/interpreter.md @@ -0,0 +1,601 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.homestead.state" "account_has_code_or_nonce". +Axiom ethereum_homestead_state_imports_begin_transaction : + IsImported globals "ethereum.homestead.state" "begin_transaction". +Axiom ethereum_homestead_state_imports_commit_transaction : + IsImported globals "ethereum.homestead.state" "commit_transaction". +Axiom ethereum_homestead_state_imports_destroy_storage : + IsImported globals "ethereum.homestead.state" "destroy_storage". +Axiom ethereum_homestead_state_imports_move_ether : + IsImported globals "ethereum.homestead.state" "move_ether". +Axiom ethereum_homestead_state_imports_rollback_transaction : + IsImported globals "ethereum.homestead.state" "rollback_transaction". +Axiom ethereum_homestead_state_imports_set_code : + IsImported globals "ethereum.homestead.state" "set_code". +Axiom ethereum_homestead_state_imports_touch_account : + IsImported globals "ethereum.homestead.state" "touch_account". + +Axiom ethereum_homestead_vm_imports_Message : + IsImported globals "ethereum.homestead.vm" "Message". + +Axiom ethereum_homestead_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.homestead.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_homestead_vm_imports_Environment : + IsImported globals "ethereum.homestead.vm" "Environment". +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.homestead.vm.exceptions" "AddressCollision". +Axiom ethereum_homestead_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.homestead.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_homestead_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.homestead.vm.exceptions" "InvalidOpcode". +Axiom ethereum_homestead_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.homestead.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_homestead_vm_instructions_imports_Ops : + IsImported globals "ethereum.homestead.vm.instructions" "Ops". +Axiom ethereum_homestead_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.homestead.vm.instructions" "op_implementation". + +Axiom ethereum_homestead_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.homestead.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/memory.md new file mode 100644 index 00000000..02bc3223 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..7435b8be --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/__init__.md @@ -0,0 +1,74 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_homestead_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.homestead.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..a52d4947 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.homestead.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_buffer_read : + IsImported globals "ethereum.homestead.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..ff669eaf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.homestead.vm.gas" "GAS_IDENTITY". +Axiom ethereum_homestead_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..79e2d2ea --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/mapping.md @@ -0,0 +1,57 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_homestead_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_homestead_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_homestead_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_homestead_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_homestead_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_homestead_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_homestead_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..4c78837d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.homestead.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_homestead_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..1109894f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.homestead.vm.gas" "GAS_SHA256". +Axiom ethereum_homestead_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/runtime.md new file mode 100644 index 00000000..8168f104 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_vm_instructions_imports_Ops : + IsImported globals "ethereum.homestead.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/stack.md new file mode 100644 index 00000000..bb12bfd0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/homestead/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/homestead/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.homestead.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.homestead.vm.exceptions" "StackOverflowError". +Axiom ethereum_homestead_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.homestead.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/__init__.md new file mode 100644 index 00000000..b6586013 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/__init__.md @@ -0,0 +1,31 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 9069000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/blocks.md new file mode 100644 index 00000000..6321328e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/blocks.md @@ -0,0 +1,91 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Bloom : + IsImported globals "ethereum.istanbul.fork_types" "Bloom". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". + +Axiom ethereum_istanbul_transactions_imports_Transaction : + IsImported globals "ethereum.istanbul.transactions" "Transaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/bloom.md new file mode 100644 index 00000000..0640488d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". + +Axiom ethereum_istanbul_fork_types_imports_Bloom : + IsImported globals "ethereum.istanbul.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/fork.md new file mode 100644 index 00000000..5443c537 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/fork.md @@ -0,0 +1,2862 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_imports_vm : + IsImported globals "ethereum.istanbul" "vm". + +Axiom ethereum_istanbul_blocks_imports_Block : + IsImported globals "ethereum.istanbul.blocks" "Block". +Axiom ethereum_istanbul_blocks_imports_Header : + IsImported globals "ethereum.istanbul.blocks" "Header". +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". +Axiom ethereum_istanbul_blocks_imports_Receipt : + IsImported globals "ethereum.istanbul.blocks" "Receipt". + +Axiom ethereum_istanbul_bloom_imports_logs_bloom : + IsImported globals "ethereum.istanbul.bloom" "logs_bloom". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Bloom : + IsImported globals "ethereum.istanbul.fork_types" "Bloom". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". + +Axiom ethereum_istanbul_state_imports_State : + IsImported globals "ethereum.istanbul.state" "State". +Axiom ethereum_istanbul_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.istanbul.state" "account_exists_and_is_empty". +Axiom ethereum_istanbul_state_imports_create_ether : + IsImported globals "ethereum.istanbul.state" "create_ether". +Axiom ethereum_istanbul_state_imports_destroy_account : + IsImported globals "ethereum.istanbul.state" "destroy_account". +Axiom ethereum_istanbul_state_imports_get_account : + IsImported globals "ethereum.istanbul.state" "get_account". +Axiom ethereum_istanbul_state_imports_increment_nonce : + IsImported globals "ethereum.istanbul.state" "increment_nonce". +Axiom ethereum_istanbul_state_imports_set_account_balance : + IsImported globals "ethereum.istanbul.state" "set_account_balance". +Axiom ethereum_istanbul_state_imports_state_root : + IsImported globals "ethereum.istanbul.state" "state_root". + +Axiom ethereum_istanbul_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.istanbul.transactions" "TX_BASE_COST". +Axiom ethereum_istanbul_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.istanbul.transactions" "TX_CREATE_COST". +Axiom ethereum_istanbul_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.istanbul.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_istanbul_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.istanbul.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_istanbul_transactions_imports_Transaction : + IsImported globals "ethereum.istanbul.transactions" "Transaction". + +Axiom ethereum_istanbul_trie_imports_Trie : + IsImported globals "ethereum.istanbul.trie" "Trie". +Axiom ethereum_istanbul_trie_imports_root : + IsImported globals "ethereum.istanbul.trie" "root". +Axiom ethereum_istanbul_trie_imports_trie_set : + IsImported globals "ethereum.istanbul.trie" "trie_set". + +Axiom ethereum_istanbul_utils_message_imports_prepare_message : + IsImported globals "ethereum.istanbul.utils.message" "prepare_message". + +Axiom ethereum_istanbul_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.istanbul.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |); + M.get_name (| globals, locals_stack, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "v" |); M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/fork_types.md new file mode 100644 index 00000000..ad6751a6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/state.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/state.md new file mode 100644 index 00000000..577d2ec2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/state.md @@ -0,0 +1,1391 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_istanbul_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.istanbul.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_istanbul_fork_types_imports_Account : + IsImported globals "ethereum.istanbul.fork_types" "Account". +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". + +Axiom ethereum_istanbul_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.istanbul.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_istanbul_trie_imports_Trie : + IsImported globals "ethereum.istanbul.trie" "Trie". +Axiom ethereum_istanbul_trie_imports_copy_trie : + IsImported globals "ethereum.istanbul.trie" "copy_trie". +Axiom ethereum_istanbul_trie_imports_root : + IsImported globals "ethereum.istanbul.trie" "root". +Axiom ethereum_istanbul_trie_imports_trie_get : + IsImported globals "ethereum.istanbul.trie" "trie_get". +Axiom ethereum_istanbul_trie_imports_trie_set : + IsImported globals "ethereum.istanbul.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom mark_account_created_in_globals : + IsInGlobals globals "mark_account_created" (make_function mark_account_created). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "_" |); M.get_name (| globals, locals_stack, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "original_account_trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "original_value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "original_value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_original_in_globals : + IsInGlobals globals "get_storage_original" (make_function get_storage_original). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/transactions.md new file mode 100644 index 00000000..d5247160 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/transactions.md @@ -0,0 +1,63 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/trie.md new file mode 100644 index 00000000..1ed7a911 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/trie.md @@ -0,0 +1,1639 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_constantinople_imports_trie : + IsImported globals "ethereum.constantinople" "trie". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_istanbul_blocks_imports_Receipt : + IsImported globals "ethereum.istanbul.blocks" "Receipt". + +Axiom ethereum_istanbul_fork_types_imports_Account : + IsImported globals "ethereum.istanbul.fork_types" "Account". +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". +Axiom ethereum_istanbul_fork_types_imports_encode_account : + IsImported globals "ethereum.istanbul.fork_types" "encode_account". + +Axiom ethereum_istanbul_transactions_imports_Transaction : + IsImported globals "ethereum.istanbul.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Receipt" |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/__init__.md new file mode 100644 index 00000000..fd6a5a66 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/address.md new file mode 100644 index 00000000..b32bfa4c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this istanbul version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/hexadecimal.md new file mode 100644 index 00000000..a97caf62 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Istanbul types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Bloom : + IsImported globals "ethereum.istanbul.fork_types" "Bloom". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/message.md new file mode 100644 index 00000000..d9db9eb7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/utils/message.md @@ -0,0 +1,224 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_state_imports_get_account : + IsImported globals "ethereum.istanbul.state" "get_account". + +Axiom ethereum_istanbul_vm_imports_Environment : + IsImported globals "ethereum.istanbul.vm" "Environment". +Axiom ethereum_istanbul_vm_imports_Message : + IsImported globals "ethereum.istanbul.vm" "Message". + +Axiom ethereum_istanbul_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.istanbul.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/__init__.md new file mode 100644 index 00000000..51d56325 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/__init__.md @@ -0,0 +1,257 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_state_imports_State : + IsImported globals "ethereum.istanbul.state" "State". +Axiom ethereum_istanbul_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.istanbul.state" "account_exists_and_is_empty". + +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/exceptions.md new file mode 100644 index 00000000..ad130164 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/exceptions.md @@ -0,0 +1,171 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidParameter : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/gas.md new file mode 100644 index 00000000..5bc4628e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/gas.md @@ -0,0 +1,968 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 800 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/__init__.md new file mode 100644 index 00000000..c7a30111 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_istanbul_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.istanbul.vm.instructions" "arithmetic". + +Axiom ethereum_istanbul_vm_instructions_imports_bitwise : + IsImported globals "ethereum.istanbul.vm.instructions" "bitwise". + +Axiom ethereum_istanbul_vm_instructions_imports_block : + IsImported globals "ethereum.istanbul.vm.instructions" "block". + +Axiom ethereum_istanbul_vm_instructions_imports_comparison : + IsImported globals "ethereum.istanbul.vm.instructions" "comparison". + +Axiom ethereum_istanbul_vm_instructions_imports_control_flow : + IsImported globals "ethereum.istanbul.vm.instructions" "control_flow". + +Axiom ethereum_istanbul_vm_instructions_imports_environment : + IsImported globals "ethereum.istanbul.vm.instructions" "environment". + +Axiom ethereum_istanbul_vm_instructions_imports_keccak : + IsImported globals "ethereum.istanbul.vm.instructions" "keccak". + +Axiom ethereum_istanbul_vm_instructions_imports_log : + IsImported globals "ethereum.istanbul.vm.instructions" "log". + +Axiom ethereum_istanbul_vm_instructions_imports_memory : + IsImported globals "ethereum.istanbul.vm.instructions" "memory". + +Axiom ethereum_istanbul_vm_instructions_imports_stack : + IsImported globals "ethereum.istanbul.vm.instructions" "stack". + +Axiom ethereum_istanbul_vm_instructions_imports_storage : + IsImported globals "ethereum.istanbul.vm.instructions" "storage". + +Axiom ethereum_istanbul_vm_instructions_imports_system : + IsImported globals "ethereum.istanbul.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/arithmetic.md new file mode 100644 index 00000000..2d6a9d5b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_istanbul_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_LOW". +Axiom ethereum_istanbul_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_MID". +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/bitwise.md new file mode 100644 index 00000000..79302ed9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/block.md new file mode 100644 index 00000000..61a1fbe0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/block.md @@ -0,0 +1,426 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom chain_id_in_globals : + IsInGlobals globals "chain_id" (make_function chain_id). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/comparison.md new file mode 100644 index 00000000..dfbcac16 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/control_flow.md new file mode 100644 index 00000000..d9a640b4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_HIGH". +Axiom ethereum_istanbul_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_istanbul_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_MID". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.istanbul.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/environment.md new file mode 100644 index 00000000..5d39ffc8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/environment.md @@ -0,0 +1,1444 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.istanbul.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_istanbul_state_imports_get_account : + IsImported globals "ethereum.istanbul.state" "get_account". + +Axiom ethereum_istanbul_utils_address_imports_to_address : + IsImported globals "ethereum.istanbul.utils.address" "to_address". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". +Axiom ethereum_istanbul_vm_memory_imports_memory_write : + IsImported globals "ethereum.istanbul.vm.memory" "memory_write". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BALANCE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_CODE_HASH : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CODE_HASH". +Axiom ethereum_istanbul_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_COPY". +Axiom ethereum_istanbul_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_istanbul_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_istanbul_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_CODE_HASH" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom self_balance_in_globals : + IsInGlobals globals "self_balance" (make_function self_balance). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/keccak.md new file mode 100644 index 00000000..6821fd5d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_KECCAK256". +Axiom ethereum_istanbul_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.istanbul.vm.memory" "memory_read_bytes". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/log.md new file mode 100644 index 00000000..f43b9dbd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.istanbul.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_LOG". +Axiom ethereum_istanbul_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_istanbul_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.istanbul.vm.memory" "memory_read_bytes". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/memory.md new file mode 100644 index 00000000..ce2c168d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.istanbul.vm.memory" "memory_read_bytes". +Axiom ethereum_istanbul_vm_memory_imports_memory_write : + IsImported globals "ethereum.istanbul.vm.memory" "memory_write". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/stack.md new file mode 100644 index 00000000..d917904e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". +Axiom ethereum_istanbul_vm_imports_stack : + IsImported globals "ethereum.istanbul.vm" "stack". + +Axiom ethereum_istanbul_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.istanbul.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/storage.md new file mode 100644 index 00000000..73ade4c7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/storage.md @@ -0,0 +1,433 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_istanbul_state_imports_get_storage : + IsImported globals "ethereum.istanbul.state" "get_storage". +Axiom ethereum_istanbul_state_imports_get_storage_original : + IsImported globals "ethereum.istanbul.state" "get_storage_original". +Axiom ethereum_istanbul_state_imports_set_storage : + IsImported globals "ethereum.istanbul.state" "set_storage". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfGasError". +Axiom ethereum_istanbul_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.istanbul.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_istanbul_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SLOAD". +Axiom ethereum_istanbul_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_istanbul_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_istanbul_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |), + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/system.md new file mode 100644 index 00000000..b54396f7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/instructions/system.md @@ -0,0 +1,2178 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.istanbul.state" "account_exists_and_is_empty". +Axiom ethereum_istanbul_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.istanbul.state" "account_has_code_or_nonce". +Axiom ethereum_istanbul_state_imports_get_account : + IsImported globals "ethereum.istanbul.state" "get_account". +Axiom ethereum_istanbul_state_imports_increment_nonce : + IsImported globals "ethereum.istanbul.state" "increment_nonce". +Axiom ethereum_istanbul_state_imports_is_account_alive : + IsImported globals "ethereum.istanbul.state" "is_account_alive". +Axiom ethereum_istanbul_state_imports_set_account_balance : + IsImported globals "ethereum.istanbul.state" "set_account_balance". + +Axiom ethereum_istanbul_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.istanbul.utils.address" "compute_contract_address". +Axiom ethereum_istanbul_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.istanbul.utils.address" "compute_create2_contract_address". +Axiom ethereum_istanbul_utils_address_imports_to_address : + IsImported globals "ethereum.istanbul.utils.address" "to_address". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". +Axiom ethereum_istanbul_vm_imports_Message : + IsImported globals "ethereum.istanbul.vm" "Message". +Axiom ethereum_istanbul_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.istanbul.vm" "incorporate_child_on_error". +Axiom ethereum_istanbul_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.istanbul.vm" "incorporate_child_on_success". + +Axiom ethereum_istanbul_vm_exceptions_imports_Revert : + IsImported globals "ethereum.istanbul.vm.exceptions" "Revert". +Axiom ethereum_istanbul_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.istanbul.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CALL". +Axiom ethereum_istanbul_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CREATE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_istanbul_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_istanbul_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_istanbul_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_istanbul_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_ZERO". +Axiom ethereum_istanbul_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.istanbul.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_message_call_gas". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". +Axiom ethereum_istanbul_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.istanbul.vm.gas" "max_message_call_gas". + +Axiom ethereum_istanbul_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.istanbul.vm.memory" "memory_read_bytes". +Axiom ethereum_istanbul_vm_memory_imports_memory_write : + IsImported globals "ethereum.istanbul.vm.memory" "memory_write". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/interpreter.md new file mode 100644 index 00000000..6f3a0fde --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/interpreter.md @@ -0,0 +1,693 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.istanbul.state" "account_exists_and_is_empty". +Axiom ethereum_istanbul_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.istanbul.state" "account_has_code_or_nonce". +Axiom ethereum_istanbul_state_imports_begin_transaction : + IsImported globals "ethereum.istanbul.state" "begin_transaction". +Axiom ethereum_istanbul_state_imports_commit_transaction : + IsImported globals "ethereum.istanbul.state" "commit_transaction". +Axiom ethereum_istanbul_state_imports_destroy_storage : + IsImported globals "ethereum.istanbul.state" "destroy_storage". +Axiom ethereum_istanbul_state_imports_increment_nonce : + IsImported globals "ethereum.istanbul.state" "increment_nonce". +Axiom ethereum_istanbul_state_imports_mark_account_created : + IsImported globals "ethereum.istanbul.state" "mark_account_created". +Axiom ethereum_istanbul_state_imports_move_ether : + IsImported globals "ethereum.istanbul.state" "move_ether". +Axiom ethereum_istanbul_state_imports_rollback_transaction : + IsImported globals "ethereum.istanbul.state" "rollback_transaction". +Axiom ethereum_istanbul_state_imports_set_code : + IsImported globals "ethereum.istanbul.state" "set_code". +Axiom ethereum_istanbul_state_imports_touch_account : + IsImported globals "ethereum.istanbul.state" "touch_account". + +Axiom ethereum_istanbul_vm_imports_Message : + IsImported globals "ethereum.istanbul.vm" "Message". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_istanbul_vm_imports_Environment : + IsImported globals "ethereum.istanbul.vm" "Environment". +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.istanbul.vm.exceptions" "AddressCollision". +Axiom ethereum_istanbul_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.istanbul.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_istanbul_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.istanbul.vm.exceptions" "InvalidOpcode". +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfGasError". +Axiom ethereum_istanbul_vm_exceptions_imports_Revert : + IsImported globals "ethereum.istanbul.vm.exceptions" "Revert". +Axiom ethereum_istanbul_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.istanbul.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_istanbul_vm_instructions_imports_Ops : + IsImported globals "ethereum.istanbul.vm.instructions" "Ops". +Axiom ethereum_istanbul_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.istanbul.vm.instructions" "op_implementation". + +Axiom ethereum_istanbul_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.istanbul.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/memory.md new file mode 100644 index 00000000..0182a633 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..4fb15923 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/__init__.md @@ -0,0 +1,124 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_istanbul_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.istanbul.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..0404be0d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". + +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..e565744d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,144 @@ +# ๐Ÿ“ blake2f.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/blake2f.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.precompiled_contracts.blake2f". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.istanbul.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, locals_stack, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, locals_stack, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, locals_stack, "rounds" |); + M.get_name (| globals, locals_stack, "h" |); + M.get_name (| globals, locals_stack, "m" |); + M.get_name (| globals, locals_stack, "t_0" |); + M.get_name (| globals, locals_stack, "t_1" |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom blake2f_in_globals : + IsInGlobals globals "blake2f" (make_function blake2f). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..b6665490 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..abdd14e2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_IDENTITY". +Axiom ethereum_istanbul_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..7d827a4c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/mapping.md @@ -0,0 +1,80 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_istanbul_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_istanbul_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_istanbul_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_istanbul_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_istanbul_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_istanbul_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_istanbul_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_istanbul_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_istanbul_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..a7530673 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/modexp.md @@ -0,0 +1,560 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "exp_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.floor_div (| + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_mult_complexity" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "adjusted_exp_length" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition get_mult_complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Estimate the complexity of performing Karatsuba multiplication. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 64 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |), + Constant.int 4 + |), + BinOp.mult (| + Constant.int 96, + M.get_name (| globals, locals_stack, "x" |) + |) + |), + Constant.int 3072 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |), + Constant.int 16 + |), + BinOp.mult (| + Constant.int 480, + M.get_name (| globals, locals_stack, "x" |) + |) + |), + Constant.int 199680 + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_mult_complexity_in_globals : + IsInGlobals globals "get_mult_complexity" (make_function get_mult_complexity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..5febbfd6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_istanbul_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..ae4d9cd8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SHA256". +Axiom ethereum_istanbul_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/runtime.md new file mode 100644 index 00000000..163560a6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_vm_instructions_imports_Ops : + IsImported globals "ethereum.istanbul.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/stack.md new file mode 100644 index 00000000..98724d75 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/istanbul/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/istanbul/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.istanbul.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_istanbul_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.istanbul.vm.exceptions" "StackOverflowError". +Axiom ethereum_istanbul_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.istanbul.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/london/__init__.md new file mode 100644 index 00000000..93ba5dcd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/__init__.md @@ -0,0 +1,30 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +The London fork overhauls the transaction fee market, changes gas refunds, +reserves a contract prefix for future use, and delays the difficulty bomb. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 12965000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/london/blocks.md new file mode 100644 index 00000000..ed9ab344 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/blocks.md @@ -0,0 +1,93 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Bloom : + IsImported globals "ethereum.london.fork_types" "Bloom". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". + +Axiom ethereum_london_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.london.transactions" "LegacyTransaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/london/bloom.md new file mode 100644 index 00000000..78e6a29b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". + +Axiom ethereum_london_fork_types_imports_Bloom : + IsImported globals "ethereum.london.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/london/fork.md new file mode 100644 index 00000000..0b1d8639 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/fork.md @@ -0,0 +1,3628 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_imports_FORK_CRITERIA : + IsImported globals "ethereum.london" "FORK_CRITERIA". +Axiom ethereum_london_imports_vm : + IsImported globals "ethereum.london" "vm". + +Axiom ethereum_london_blocks_imports_Block : + IsImported globals "ethereum.london.blocks" "Block". +Axiom ethereum_london_blocks_imports_Header : + IsImported globals "ethereum.london.blocks" "Header". +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". +Axiom ethereum_london_blocks_imports_Receipt : + IsImported globals "ethereum.london.blocks" "Receipt". + +Axiom ethereum_london_bloom_imports_logs_bloom : + IsImported globals "ethereum.london.bloom" "logs_bloom". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Bloom : + IsImported globals "ethereum.london.fork_types" "Bloom". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". + +Axiom ethereum_london_state_imports_State : + IsImported globals "ethereum.london.state" "State". +Axiom ethereum_london_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.london.state" "account_exists_and_is_empty". +Axiom ethereum_london_state_imports_create_ether : + IsImported globals "ethereum.london.state" "create_ether". +Axiom ethereum_london_state_imports_destroy_account : + IsImported globals "ethereum.london.state" "destroy_account". +Axiom ethereum_london_state_imports_get_account : + IsImported globals "ethereum.london.state" "get_account". +Axiom ethereum_london_state_imports_increment_nonce : + IsImported globals "ethereum.london.state" "increment_nonce". +Axiom ethereum_london_state_imports_set_account_balance : + IsImported globals "ethereum.london.state" "set_account_balance". +Axiom ethereum_london_state_imports_state_root : + IsImported globals "ethereum.london.state" "state_root". + +Axiom ethereum_london_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.london.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_london_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.london.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_london_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.london.transactions" "TX_BASE_COST". +Axiom ethereum_london_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.london.transactions" "TX_CREATE_COST". +Axiom ethereum_london_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.london.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_london_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.london.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_london_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.london.transactions" "AccessListTransaction". +Axiom ethereum_london_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.london.transactions" "FeeMarketTransaction". +Axiom ethereum_london_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.london.transactions" "LegacyTransaction". +Axiom ethereum_london_transactions_imports_Transaction : + IsImported globals "ethereum.london.transactions" "Transaction". +Axiom ethereum_london_transactions_imports_decode_transaction : + IsImported globals "ethereum.london.transactions" "decode_transaction". +Axiom ethereum_london_transactions_imports_encode_transaction : + IsImported globals "ethereum.london.transactions" "encode_transaction". + +Axiom ethereum_london_trie_imports_Trie : + IsImported globals "ethereum.london.trie" "Trie". +Axiom ethereum_london_trie_imports_root : + IsImported globals "ethereum.london.trie" "root". +Axiom ethereum_london_trie_imports_trie_set : + IsImported globals "ethereum.london.trie" "trie_set". + +Axiom ethereum_london_utils_message_imports_prepare_message : + IsImported globals "ethereum.london.utils.message" "prepare_message". + +Axiom ethereum_london_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.london.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition INITIAL_BASE_FEE : Value.t := M.run ltac:(M.monadic ( + Constant.int 1000000000 +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 9700000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas"; "is_fork_block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + is_fork_block : + Whether the block is the fork block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + " in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_fork_block" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "INITIAL_BASE_FEE" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_limit" |); + M.get_name (| globals, locals_stack, "parent_gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_target" |), + M.get_name (| globals, locals_stack, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_base_fee_per_gas_in_globals : + IsInGlobals globals "calculate_base_fee_per_gas" (make_function calculate_base_fee_per_gas). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "is_fork_block" , + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "FORK_CRITERIA" |), "block_number" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "base_fee_per_gas" |); + M.get_name (| globals, locals_stack, "is_fork_block" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |); + M.get_name (| globals, locals_stack, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "base_fee_per_gas" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "map" |), + make_list [ + M.get_name (| globals, locals_stack, "decode_transaction" |); + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "encode_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "base_fee_per_gas" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "_address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |), + M.get_name (| globals, locals_stack, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_2930_in_globals : + IsInGlobals globals "signing_hash_2930" (make_function signing_hash_2930). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_1559_in_globals : + IsInGlobals globals "signing_hash_1559" (make_function signing_hash_1559). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/london/fork_types.md new file mode 100644 index 00000000..f78ff796 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/state.md b/docs/revm-python-spec/revm-verif/spec-coq/london/state.md new file mode 100644 index 00000000..265409b2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/state.md @@ -0,0 +1,1391 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_london_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.london.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_london_fork_types_imports_Account : + IsImported globals "ethereum.london.fork_types" "Account". +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". + +Axiom ethereum_london_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.london.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_london_trie_imports_Trie : + IsImported globals "ethereum.london.trie" "Trie". +Axiom ethereum_london_trie_imports_copy_trie : + IsImported globals "ethereum.london.trie" "copy_trie". +Axiom ethereum_london_trie_imports_root : + IsImported globals "ethereum.london.trie" "root". +Axiom ethereum_london_trie_imports_trie_get : + IsImported globals "ethereum.london.trie" "trie_get". +Axiom ethereum_london_trie_imports_trie_set : + IsImported globals "ethereum.london.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom mark_account_created_in_globals : + IsInGlobals globals "mark_account_created" (make_function mark_account_created). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "_" |); M.get_name (| globals, locals_stack, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "original_account_trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "original_value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "original_value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_original_in_globals : + IsInGlobals globals "get_storage_original" (make_function get_storage_original). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/london/transactions.md new file mode 100644 index 00000000..ed57f213 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/transactions.md @@ -0,0 +1,306 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AccessListTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition FeeMarketTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_transaction_in_globals : + IsInGlobals globals "encode_transaction" (make_function encode_transaction). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom decode_transaction_in_globals : + IsInGlobals globals "decode_transaction" (make_function decode_transaction). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/london/trie.md new file mode 100644 index 00000000..16818d41 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/trie.md @@ -0,0 +1,1645 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_berlin_imports_trie : + IsImported globals "ethereum.berlin" "trie". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_london_blocks_imports_Receipt : + IsImported globals "ethereum.london.blocks" "Receipt". + +Axiom ethereum_london_fork_types_imports_Account : + IsImported globals "ethereum.london.fork_types" "Account". +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". +Axiom ethereum_london_fork_types_imports_encode_account : + IsImported globals "ethereum.london.fork_types" "encode_account". + +Axiom ethereum_london_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.london.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/london/utils/__init__.md new file mode 100644 index 00000000..d28c183b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/london/utils/address.md new file mode 100644 index 00000000..3b5bd9fa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this london version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/london/utils/hexadecimal.md new file mode 100644 index 00000000..d554d3d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +London types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Bloom : + IsImported globals "ethereum.london.fork_types" "Bloom". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/london/utils/message.md new file mode 100644 index 00000000..0ea5061e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/utils/message.md @@ -0,0 +1,278 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_state_imports_get_account : + IsImported globals "ethereum.london.state" "get_account". + +Axiom ethereum_london_vm_imports_Environment : + IsImported globals "ethereum.london.vm" "Environment". +Axiom ethereum_london_vm_imports_Message : + IsImported globals "ethereum.london.vm" "Message". + +Axiom ethereum_london_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.london.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_london_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.london.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, locals_stack, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/__init__.md new file mode 100644 index 00000000..ed8e5a6c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/__init__.md @@ -0,0 +1,273 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_state_imports_State : + IsImported globals "ethereum.london.state" "State". +Axiom ethereum_london_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.london.state" "account_exists_and_is_empty". + +Axiom ethereum_london_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/exceptions.md new file mode 100644 index 00000000..7d373e57 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/exceptions.md @@ -0,0 +1,181 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidParameter : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidContractPrefix : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/gas.md new file mode 100644 index 00000000..f8e3c8d7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/gas.md @@ -0,0 +1,938 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.london.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/__init__.md new file mode 100644 index 00000000..6d597349 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_london_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.london.vm.instructions" "arithmetic". + +Axiom ethereum_london_vm_instructions_imports_bitwise : + IsImported globals "ethereum.london.vm.instructions" "bitwise". + +Axiom ethereum_london_vm_instructions_imports_block : + IsImported globals "ethereum.london.vm.instructions" "block". + +Axiom ethereum_london_vm_instructions_imports_comparison : + IsImported globals "ethereum.london.vm.instructions" "comparison". + +Axiom ethereum_london_vm_instructions_imports_control_flow : + IsImported globals "ethereum.london.vm.instructions" "control_flow". + +Axiom ethereum_london_vm_instructions_imports_environment : + IsImported globals "ethereum.london.vm.instructions" "environment". + +Axiom ethereum_london_vm_instructions_imports_keccak : + IsImported globals "ethereum.london.vm.instructions" "keccak". + +Axiom ethereum_london_vm_instructions_imports_log : + IsImported globals "ethereum.london.vm.instructions" "log". + +Axiom ethereum_london_vm_instructions_imports_memory : + IsImported globals "ethereum.london.vm.instructions" "memory". + +Axiom ethereum_london_vm_instructions_imports_stack : + IsImported globals "ethereum.london.vm.instructions" "stack". + +Axiom ethereum_london_vm_instructions_imports_storage : + IsImported globals "ethereum.london.vm.instructions" "storage". + +Axiom ethereum_london_vm_instructions_imports_system : + IsImported globals "ethereum.london.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/arithmetic.md new file mode 100644 index 00000000..e15b21a9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.london.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_london_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.london.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_london_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_LOW". +Axiom ethereum_london_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.london.vm.gas" "GAS_MID". +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/bitwise.md new file mode 100644 index 00000000..e25a7e5f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/block.md new file mode 100644 index 00000000..a2635431 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/block.md @@ -0,0 +1,426 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.london.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom chain_id_in_globals : + IsInGlobals globals "chain_id" (make_function chain_id). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/comparison.md new file mode 100644 index 00000000..a303b5a4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/control_flow.md new file mode 100644 index 00000000..b3a382d6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.london.vm.gas" "GAS_HIGH". +Axiom ethereum_london_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.london.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_london_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.london.vm.gas" "GAS_MID". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.london.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/environment.md new file mode 100644 index 00000000..1623acb8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/environment.md @@ -0,0 +1,1610 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.london.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_london_state_imports_get_account : + IsImported globals "ethereum.london.state" "get_account". + +Axiom ethereum_london_utils_address_imports_to_address : + IsImported globals "ethereum.london.utils.address" "to_address". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". +Axiom ethereum_london_vm_memory_imports_memory_write : + IsImported globals "ethereum.london.vm.memory" "memory_write". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.london.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_london_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.london.vm.gas" "GAS_COPY". +Axiom ethereum_london_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.london.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_london_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.london.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom self_balance_in_globals : + IsInGlobals globals "self_balance" (make_function self_balance). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom base_fee_in_globals : + IsInGlobals globals "base_fee" (make_function base_fee). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/keccak.md new file mode 100644 index 00000000..e8fe5082 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.london.vm.gas" "GAS_KECCAK256". +Axiom ethereum_london_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.london.vm.memory" "memory_read_bytes". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/log.md new file mode 100644 index 00000000..1732e7bf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.london.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_london_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.london.vm.gas" "GAS_LOG". +Axiom ethereum_london_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.london.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_london_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.london.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.london.vm.memory" "memory_read_bytes". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/memory.md new file mode 100644 index 00000000..0f35d89e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.london.vm.memory" "memory_read_bytes". +Axiom ethereum_london_vm_memory_imports_memory_write : + IsImported globals "ethereum.london.vm.memory" "memory_write". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/stack.md new file mode 100644 index 00000000..e0e80055 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". +Axiom ethereum_london_vm_imports_stack : + IsImported globals "ethereum.london.vm" "stack". + +Axiom ethereum_london_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.london.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/storage.md new file mode 100644 index 00000000..3282c75e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/storage.md @@ -0,0 +1,512 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_state_imports_get_storage : + IsImported globals "ethereum.london.state" "get_storage". +Axiom ethereum_london_state_imports_get_storage_original : + IsImported globals "ethereum.london.state" "get_storage_original". +Axiom ethereum_london_state_imports_set_storage : + IsImported globals "ethereum.london.state" "set_storage". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.london.vm.exceptions" "OutOfGasError". +Axiom ethereum_london_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.london.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_london_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.london.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_london_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.london.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_london_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.london.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_london_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.london.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_london_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.london.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_london_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/system.md new file mode 100644 index 00000000..cae83770 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/instructions/system.md @@ -0,0 +1,2276 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.london.state" "account_exists_and_is_empty". +Axiom ethereum_london_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.london.state" "account_has_code_or_nonce". +Axiom ethereum_london_state_imports_get_account : + IsImported globals "ethereum.london.state" "get_account". +Axiom ethereum_london_state_imports_increment_nonce : + IsImported globals "ethereum.london.state" "increment_nonce". +Axiom ethereum_london_state_imports_is_account_alive : + IsImported globals "ethereum.london.state" "is_account_alive". +Axiom ethereum_london_state_imports_set_account_balance : + IsImported globals "ethereum.london.state" "set_account_balance". + +Axiom ethereum_london_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.london.utils.address" "compute_contract_address". +Axiom ethereum_london_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.london.utils.address" "compute_create2_contract_address". +Axiom ethereum_london_utils_address_imports_to_address : + IsImported globals "ethereum.london.utils.address" "to_address". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". +Axiom ethereum_london_vm_imports_Message : + IsImported globals "ethereum.london.vm" "Message". +Axiom ethereum_london_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.london.vm" "incorporate_child_on_error". +Axiom ethereum_london_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.london.vm" "incorporate_child_on_success". + +Axiom ethereum_london_vm_exceptions_imports_Revert : + IsImported globals "ethereum.london.vm.exceptions" "Revert". +Axiom ethereum_london_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.london.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_london_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.london.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_london_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_london_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.london.vm.gas" "GAS_CREATE". +Axiom ethereum_london_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_london_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.london.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_london_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.london.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_london_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.london.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_london_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_london_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.london.vm.gas" "GAS_ZERO". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.london.vm.gas" "calculate_message_call_gas". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". +Axiom ethereum_london_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.london.vm.gas" "max_message_call_gas". + +Axiom ethereum_london_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.london.vm.memory" "memory_read_bytes". +Axiom ethereum_london_vm_memory_imports_memory_write : + IsImported globals "ethereum.london.vm.memory" "memory_write". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "beneficiary" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/interpreter.md new file mode 100644 index 00000000..6580e1f4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/interpreter.md @@ -0,0 +1,695 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.london.state" "account_exists_and_is_empty". +Axiom ethereum_london_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.london.state" "account_has_code_or_nonce". +Axiom ethereum_london_state_imports_begin_transaction : + IsImported globals "ethereum.london.state" "begin_transaction". +Axiom ethereum_london_state_imports_commit_transaction : + IsImported globals "ethereum.london.state" "commit_transaction". +Axiom ethereum_london_state_imports_destroy_storage : + IsImported globals "ethereum.london.state" "destroy_storage". +Axiom ethereum_london_state_imports_increment_nonce : + IsImported globals "ethereum.london.state" "increment_nonce". +Axiom ethereum_london_state_imports_mark_account_created : + IsImported globals "ethereum.london.state" "mark_account_created". +Axiom ethereum_london_state_imports_move_ether : + IsImported globals "ethereum.london.state" "move_ether". +Axiom ethereum_london_state_imports_rollback_transaction : + IsImported globals "ethereum.london.state" "rollback_transaction". +Axiom ethereum_london_state_imports_set_code : + IsImported globals "ethereum.london.state" "set_code". +Axiom ethereum_london_state_imports_touch_account : + IsImported globals "ethereum.london.state" "touch_account". + +Axiom ethereum_london_vm_imports_Message : + IsImported globals "ethereum.london.vm" "Message". + +Axiom ethereum_london_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.london.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.london.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_london_vm_imports_Environment : + IsImported globals "ethereum.london.vm" "Environment". +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.london.vm.exceptions" "AddressCollision". +Axiom ethereum_london_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.london.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_london_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.london.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_london_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.london.vm.exceptions" "InvalidOpcode". +Axiom ethereum_london_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.london.vm.exceptions" "OutOfGasError". +Axiom ethereum_london_vm_exceptions_imports_Revert : + IsImported globals "ethereum.london.vm.exceptions" "Revert". +Axiom ethereum_london_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.london.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_london_vm_instructions_imports_Ops : + IsImported globals "ethereum.london.vm.instructions" "Ops". +Axiom ethereum_london_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.london.vm.instructions" "op_implementation". + +Axiom ethereum_london_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.london.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/memory.md new file mode 100644 index 00000000..9db4683e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..01f698af --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/__init__.md @@ -0,0 +1,124 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_london_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.london.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..1c6a7259 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". + +Axiom ethereum_london_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.london.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..1027ec60 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,144 @@ +# ๐Ÿ“ blake2f.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/precompiled_contracts/blake2f.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.precompiled_contracts.blake2f". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.london.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.london.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, locals_stack, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, locals_stack, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, locals_stack, "rounds" |); + M.get_name (| globals, locals_stack, "h" |); + M.get_name (| globals, locals_stack, "m" |); + M.get_name (| globals, locals_stack, "t_0" |); + M.get_name (| globals, locals_stack, "t_1" |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom blake2f_in_globals : + IsInGlobals globals "blake2f" (make_function blake2f). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..aaf900d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.london.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..3bdfe617 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.london.vm.gas" "GAS_IDENTITY". +Axiom ethereum_london_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..965aafc6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/mapping.md @@ -0,0 +1,80 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_london_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.london.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_london_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.london.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_london_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.london.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_london_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.london.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_london_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.london.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_london_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.london.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_london_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.london.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_london_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.london.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_london_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.london.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..285538e8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/modexp.md @@ -0,0 +1,700 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |); + M.get_name (| globals, locals_stack, "exp_length" |); + M.get_name (| globals, locals_stack, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Axiom complexity_in_globals : + IsInGlobals globals "complexity" (make_function complexity). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, locals_stack, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, locals_stack, "length_part" |), + M.get_name (| globals, locals_stack, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "count" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom iterations_in_globals : + IsInGlobals globals "iterations" (make_function iterations). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, locals_stack, "complexity" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, locals_stack, "iterations" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |); + M.get_name (| globals, locals_stack, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "multiplication_complexity" |), + M.get_name (| globals, locals_stack, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom gas_cost_in_globals : + IsInGlobals globals "gas_cost" (make_function gas_cost). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..bde8b56b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.london.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_london_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..3d1d1a78 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.london.vm.gas" "GAS_SHA256". +Axiom ethereum_london_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/runtime.md new file mode 100644 index 00000000..fb913a36 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_vm_instructions_imports_Ops : + IsImported globals "ethereum.london.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/london/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/stack.md new file mode 100644 index 00000000..79fba700 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/london/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/london/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.london.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_london_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.london.vm.exceptions" "StackOverflowError". +Axiom ethereum_london_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.london.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/__init__.md new file mode 100644 index 00000000..846803b2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/__init__.md @@ -0,0 +1,30 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +The Muir Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 9200000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/blocks.md new file mode 100644 index 00000000..fc4256b7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/blocks.md @@ -0,0 +1,91 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.muir_glacier.fork_types" "Bloom". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". + +Axiom ethereum_muir_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.muir_glacier.transactions" "Transaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/bloom.md new file mode 100644 index 00000000..22aa51dc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". + +Axiom ethereum_muir_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.muir_glacier.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/fork.md new file mode 100644 index 00000000..940997c1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/fork.md @@ -0,0 +1,2862 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_imports_vm : + IsImported globals "ethereum.muir_glacier" "vm". + +Axiom ethereum_muir_glacier_blocks_imports_Block : + IsImported globals "ethereum.muir_glacier.blocks" "Block". +Axiom ethereum_muir_glacier_blocks_imports_Header : + IsImported globals "ethereum.muir_glacier.blocks" "Header". +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". +Axiom ethereum_muir_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.muir_glacier.blocks" "Receipt". + +Axiom ethereum_muir_glacier_bloom_imports_logs_bloom : + IsImported globals "ethereum.muir_glacier.bloom" "logs_bloom". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.muir_glacier.fork_types" "Bloom". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". + +Axiom ethereum_muir_glacier_state_imports_State : + IsImported globals "ethereum.muir_glacier.state" "State". +Axiom ethereum_muir_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.muir_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_muir_glacier_state_imports_create_ether : + IsImported globals "ethereum.muir_glacier.state" "create_ether". +Axiom ethereum_muir_glacier_state_imports_destroy_account : + IsImported globals "ethereum.muir_glacier.state" "destroy_account". +Axiom ethereum_muir_glacier_state_imports_get_account : + IsImported globals "ethereum.muir_glacier.state" "get_account". +Axiom ethereum_muir_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.muir_glacier.state" "increment_nonce". +Axiom ethereum_muir_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.muir_glacier.state" "set_account_balance". +Axiom ethereum_muir_glacier_state_imports_state_root : + IsImported globals "ethereum.muir_glacier.state" "state_root". + +Axiom ethereum_muir_glacier_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.muir_glacier.transactions" "TX_BASE_COST". +Axiom ethereum_muir_glacier_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.muir_glacier.transactions" "TX_CREATE_COST". +Axiom ethereum_muir_glacier_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.muir_glacier.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_muir_glacier_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.muir_glacier.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_muir_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.muir_glacier.transactions" "Transaction". + +Axiom ethereum_muir_glacier_trie_imports_Trie : + IsImported globals "ethereum.muir_glacier.trie" "Trie". +Axiom ethereum_muir_glacier_trie_imports_root : + IsImported globals "ethereum.muir_glacier.trie" "root". +Axiom ethereum_muir_glacier_trie_imports_trie_set : + IsImported globals "ethereum.muir_glacier.trie" "trie_set". + +Axiom ethereum_muir_glacier_utils_message_imports_prepare_message : + IsImported globals "ethereum.muir_glacier.utils.message" "prepare_message". + +Axiom ethereum_muir_glacier_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.muir_glacier.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 9000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |); + M.get_name (| globals, locals_stack, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "v" |); M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/fork_types.md new file mode 100644 index 00000000..0118d1ec --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/state.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/state.md new file mode 100644 index 00000000..c09fa275 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/state.md @@ -0,0 +1,1391 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_muir_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.muir_glacier.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_muir_glacier_fork_types_imports_Account : + IsImported globals "ethereum.muir_glacier.fork_types" "Account". +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". + +Axiom ethereum_muir_glacier_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.muir_glacier.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_muir_glacier_trie_imports_Trie : + IsImported globals "ethereum.muir_glacier.trie" "Trie". +Axiom ethereum_muir_glacier_trie_imports_copy_trie : + IsImported globals "ethereum.muir_glacier.trie" "copy_trie". +Axiom ethereum_muir_glacier_trie_imports_root : + IsImported globals "ethereum.muir_glacier.trie" "root". +Axiom ethereum_muir_glacier_trie_imports_trie_get : + IsImported globals "ethereum.muir_glacier.trie" "trie_get". +Axiom ethereum_muir_glacier_trie_imports_trie_set : + IsImported globals "ethereum.muir_glacier.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom mark_account_created_in_globals : + IsInGlobals globals "mark_account_created" (make_function mark_account_created). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "_" |); M.get_name (| globals, locals_stack, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "original_account_trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "original_value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "original_value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_original_in_globals : + IsInGlobals globals "get_storage_original" (make_function get_storage_original). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/transactions.md new file mode 100644 index 00000000..bca74802 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/transactions.md @@ -0,0 +1,63 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/trie.md new file mode 100644 index 00000000..6447232f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/trie.md @@ -0,0 +1,1639 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_istanbul_imports_trie : + IsImported globals "ethereum.istanbul" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_muir_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.muir_glacier.blocks" "Receipt". + +Axiom ethereum_muir_glacier_fork_types_imports_Account : + IsImported globals "ethereum.muir_glacier.fork_types" "Account". +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". +Axiom ethereum_muir_glacier_fork_types_imports_encode_account : + IsImported globals "ethereum.muir_glacier.fork_types" "encode_account". + +Axiom ethereum_muir_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.muir_glacier.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Receipt" |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/__init__.md new file mode 100644 index 00000000..fbfd2348 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/address.md new file mode 100644 index 00000000..f513c186 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this muir_glacier version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/hexadecimal.md new file mode 100644 index 00000000..ef16a85a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.muir_glacier.fork_types" "Bloom". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/message.md new file mode 100644 index 00000000..87de5a7c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/utils/message.md @@ -0,0 +1,224 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_state_imports_get_account : + IsImported globals "ethereum.muir_glacier.state" "get_account". + +Axiom ethereum_muir_glacier_vm_imports_Environment : + IsImported globals "ethereum.muir_glacier.vm" "Environment". +Axiom ethereum_muir_glacier_vm_imports_Message : + IsImported globals "ethereum.muir_glacier.vm" "Message". + +Axiom ethereum_muir_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.muir_glacier.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/__init__.md new file mode 100644 index 00000000..13621606 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/__init__.md @@ -0,0 +1,257 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_state_imports_State : + IsImported globals "ethereum.muir_glacier.state" "State". +Axiom ethereum_muir_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.muir_glacier.state" "account_exists_and_is_empty". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/exceptions.md new file mode 100644 index 00000000..6cbec4b3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/exceptions.md @@ -0,0 +1,171 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidParameter : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/gas.md new file mode 100644 index 00000000..2e7b46ea --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/gas.md @@ -0,0 +1,968 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 800 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/__init__.md new file mode 100644 index 00000000..7831ab80 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_muir_glacier_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.muir_glacier.vm.instructions" "arithmetic". + +Axiom ethereum_muir_glacier_vm_instructions_imports_bitwise : + IsImported globals "ethereum.muir_glacier.vm.instructions" "bitwise". + +Axiom ethereum_muir_glacier_vm_instructions_imports_block : + IsImported globals "ethereum.muir_glacier.vm.instructions" "block". + +Axiom ethereum_muir_glacier_vm_instructions_imports_comparison : + IsImported globals "ethereum.muir_glacier.vm.instructions" "comparison". + +Axiom ethereum_muir_glacier_vm_instructions_imports_control_flow : + IsImported globals "ethereum.muir_glacier.vm.instructions" "control_flow". + +Axiom ethereum_muir_glacier_vm_instructions_imports_environment : + IsImported globals "ethereum.muir_glacier.vm.instructions" "environment". + +Axiom ethereum_muir_glacier_vm_instructions_imports_keccak : + IsImported globals "ethereum.muir_glacier.vm.instructions" "keccak". + +Axiom ethereum_muir_glacier_vm_instructions_imports_log : + IsImported globals "ethereum.muir_glacier.vm.instructions" "log". + +Axiom ethereum_muir_glacier_vm_instructions_imports_memory : + IsImported globals "ethereum.muir_glacier.vm.instructions" "memory". + +Axiom ethereum_muir_glacier_vm_instructions_imports_stack : + IsImported globals "ethereum.muir_glacier.vm.instructions" "stack". + +Axiom ethereum_muir_glacier_vm_instructions_imports_storage : + IsImported globals "ethereum.muir_glacier.vm.instructions" "storage". + +Axiom ethereum_muir_glacier_vm_instructions_imports_system : + IsImported globals "ethereum.muir_glacier.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/arithmetic.md new file mode 100644 index 00000000..2756fd36 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_MID". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/bitwise.md new file mode 100644 index 00000000..c3de084d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/block.md new file mode 100644 index 00000000..10f1cdbe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/block.md @@ -0,0 +1,426 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom chain_id_in_globals : + IsInGlobals globals "chain_id" (make_function chain_id). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/comparison.md new file mode 100644 index 00000000..fd97e656 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/control_flow.md new file mode 100644 index 00000000..7e553dff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_HIGH". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_MID". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/environment.md new file mode 100644 index 00000000..cdb236b9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/environment.md @@ -0,0 +1,1444 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.muir_glacier.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_muir_glacier_state_imports_get_account : + IsImported globals "ethereum.muir_glacier.state" "get_account". + +Axiom ethereum_muir_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.muir_glacier.utils.address" "to_address". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". +Axiom ethereum_muir_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_write". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BALANCE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CODE_HASH : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CODE_HASH". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_COPY". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_CODE_HASH" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom self_balance_in_globals : + IsInGlobals globals "self_balance" (make_function self_balance). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/keccak.md new file mode 100644 index 00000000..d553df82 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_KECCAK256". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/log.md new file mode 100644 index 00000000..9f1af1cb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_LOG". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/memory.md new file mode 100644 index 00000000..5e421644 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_muir_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_write". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/stack.md new file mode 100644 index 00000000..0368ae71 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". +Axiom ethereum_muir_glacier_vm_imports_stack : + IsImported globals "ethereum.muir_glacier.vm" "stack". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/storage.md new file mode 100644 index 00000000..80e66982 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/storage.md @@ -0,0 +1,433 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_muir_glacier_state_imports_get_storage : + IsImported globals "ethereum.muir_glacier.state" "get_storage". +Axiom ethereum_muir_glacier_state_imports_get_storage_original : + IsImported globals "ethereum.muir_glacier.state" "get_storage_original". +Axiom ethereum_muir_glacier_state_imports_set_storage : + IsImported globals "ethereum.muir_glacier.state" "set_storage". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_muir_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SLOAD". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |), + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/system.md new file mode 100644 index 00000000..a54f352b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/instructions/system.md @@ -0,0 +1,2178 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.muir_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_muir_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.muir_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_muir_glacier_state_imports_get_account : + IsImported globals "ethereum.muir_glacier.state" "get_account". +Axiom ethereum_muir_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.muir_glacier.state" "increment_nonce". +Axiom ethereum_muir_glacier_state_imports_is_account_alive : + IsImported globals "ethereum.muir_glacier.state" "is_account_alive". +Axiom ethereum_muir_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.muir_glacier.state" "set_account_balance". + +Axiom ethereum_muir_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.muir_glacier.utils.address" "compute_contract_address". +Axiom ethereum_muir_glacier_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.muir_glacier.utils.address" "compute_create2_contract_address". +Axiom ethereum_muir_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.muir_glacier.utils.address" "to_address". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". +Axiom ethereum_muir_glacier_vm_imports_Message : + IsImported globals "ethereum.muir_glacier.vm" "Message". +Axiom ethereum_muir_glacier_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.muir_glacier.vm" "incorporate_child_on_error". +Axiom ethereum_muir_glacier_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.muir_glacier.vm" "incorporate_child_on_success". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "Revert". +Axiom ethereum_muir_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CALL". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CREATE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_ZERO". +Axiom ethereum_muir_glacier_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.muir_glacier.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_message_call_gas". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". +Axiom ethereum_muir_glacier_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "max_message_call_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_muir_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_write". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/interpreter.md new file mode 100644 index 00000000..c4c4d790 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/interpreter.md @@ -0,0 +1,693 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.muir_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_muir_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.muir_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_muir_glacier_state_imports_begin_transaction : + IsImported globals "ethereum.muir_glacier.state" "begin_transaction". +Axiom ethereum_muir_glacier_state_imports_commit_transaction : + IsImported globals "ethereum.muir_glacier.state" "commit_transaction". +Axiom ethereum_muir_glacier_state_imports_destroy_storage : + IsImported globals "ethereum.muir_glacier.state" "destroy_storage". +Axiom ethereum_muir_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.muir_glacier.state" "increment_nonce". +Axiom ethereum_muir_glacier_state_imports_mark_account_created : + IsImported globals "ethereum.muir_glacier.state" "mark_account_created". +Axiom ethereum_muir_glacier_state_imports_move_ether : + IsImported globals "ethereum.muir_glacier.state" "move_ether". +Axiom ethereum_muir_glacier_state_imports_rollback_transaction : + IsImported globals "ethereum.muir_glacier.state" "rollback_transaction". +Axiom ethereum_muir_glacier_state_imports_set_code : + IsImported globals "ethereum.muir_glacier.state" "set_code". +Axiom ethereum_muir_glacier_state_imports_touch_account : + IsImported globals "ethereum.muir_glacier.state" "touch_account". + +Axiom ethereum_muir_glacier_vm_imports_Message : + IsImported globals "ethereum.muir_glacier.vm" "Message". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_muir_glacier_vm_imports_Environment : + IsImported globals "ethereum.muir_glacier.vm" "Environment". +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "AddressCollision". +Axiom ethereum_muir_glacier_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_muir_glacier_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "InvalidOpcode". +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_muir_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "Revert". +Axiom ethereum_muir_glacier_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_muir_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.muir_glacier.vm.instructions" "Ops". +Axiom ethereum_muir_glacier_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.muir_glacier.vm.instructions" "op_implementation". + +Axiom ethereum_muir_glacier_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.muir_glacier.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/memory.md new file mode 100644 index 00000000..5eb024f6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..824a0c18 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/__init__.md @@ -0,0 +1,124 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_muir_glacier_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.muir_glacier.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..436c6448 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..f63042cc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,144 @@ +# ๐Ÿ“ blake2f.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.precompiled_contracts.blake2f". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, locals_stack, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, locals_stack, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, locals_stack, "rounds" |); + M.get_name (| globals, locals_stack, "h" |); + M.get_name (| globals, locals_stack, "m" |); + M.get_name (| globals, locals_stack, "t_0" |); + M.get_name (| globals, locals_stack, "t_1" |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom blake2f_in_globals : + IsInGlobals globals "blake2f" (make_function blake2f). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..6fa2e911 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..f2f9429a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_IDENTITY". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..e84fc896 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/mapping.md @@ -0,0 +1,80 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..9cb0e067 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/modexp.md @@ -0,0 +1,560 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "exp_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.floor_div (| + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_mult_complexity" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "adjusted_exp_length" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition get_mult_complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Estimate the complexity of performing Karatsuba multiplication. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 64 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |), + Constant.int 4 + |), + BinOp.mult (| + Constant.int 96, + M.get_name (| globals, locals_stack, "x" |) + |) + |), + Constant.int 3072 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 2 + |), + Constant.int 16 + |), + BinOp.mult (| + Constant.int 480, + M.get_name (| globals, locals_stack, "x" |) + |) + |), + Constant.int 199680 + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_mult_complexity_in_globals : + IsInGlobals globals "get_mult_complexity" (make_function get_mult_complexity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..e7ae30fb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..2bc99020 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SHA256". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/runtime.md new file mode 100644 index 00000000..b88c221c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.muir_glacier.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/stack.md new file mode 100644 index 00000000..30d7bc77 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/muir_glacier/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/muir_glacier/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.muir_glacier.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "StackOverflowError". +Axiom ethereum_muir_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/__init__.md new file mode 100644 index 00000000..0832228d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/__init__.md @@ -0,0 +1,34 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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 +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 15537394 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/blocks.md new file mode 100644 index 00000000..10f9d29c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/blocks.md @@ -0,0 +1,93 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Bloom : + IsImported globals "ethereum.paris.fork_types" "Bloom". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". + +Axiom ethereum_paris_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.paris.transactions" "LegacyTransaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/bloom.md new file mode 100644 index 00000000..f36cd9df --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". + +Axiom ethereum_paris_fork_types_imports_Bloom : + IsImported globals "ethereum.paris.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/fork.md new file mode 100644 index 00000000..aa7c0b1f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/fork.md @@ -0,0 +1,2748 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_imports_vm : + IsImported globals "ethereum.paris" "vm". + +Axiom ethereum_paris_blocks_imports_Block : + IsImported globals "ethereum.paris.blocks" "Block". +Axiom ethereum_paris_blocks_imports_Header : + IsImported globals "ethereum.paris.blocks" "Header". +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". +Axiom ethereum_paris_blocks_imports_Receipt : + IsImported globals "ethereum.paris.blocks" "Receipt". + +Axiom ethereum_paris_bloom_imports_logs_bloom : + IsImported globals "ethereum.paris.bloom" "logs_bloom". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Bloom : + IsImported globals "ethereum.paris.fork_types" "Bloom". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". + +Axiom ethereum_paris_state_imports_State : + IsImported globals "ethereum.paris.state" "State". +Axiom ethereum_paris_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.paris.state" "account_exists_and_is_empty". +Axiom ethereum_paris_state_imports_destroy_account : + IsImported globals "ethereum.paris.state" "destroy_account". +Axiom ethereum_paris_state_imports_get_account : + IsImported globals "ethereum.paris.state" "get_account". +Axiom ethereum_paris_state_imports_increment_nonce : + IsImported globals "ethereum.paris.state" "increment_nonce". +Axiom ethereum_paris_state_imports_set_account_balance : + IsImported globals "ethereum.paris.state" "set_account_balance". +Axiom ethereum_paris_state_imports_state_root : + IsImported globals "ethereum.paris.state" "state_root". + +Axiom ethereum_paris_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.paris.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_paris_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.paris.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_paris_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.paris.transactions" "TX_BASE_COST". +Axiom ethereum_paris_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.paris.transactions" "TX_CREATE_COST". +Axiom ethereum_paris_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.paris.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_paris_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.paris.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_paris_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.paris.transactions" "AccessListTransaction". +Axiom ethereum_paris_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.paris.transactions" "FeeMarketTransaction". +Axiom ethereum_paris_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.paris.transactions" "LegacyTransaction". +Axiom ethereum_paris_transactions_imports_Transaction : + IsImported globals "ethereum.paris.transactions" "Transaction". +Axiom ethereum_paris_transactions_imports_decode_transaction : + IsImported globals "ethereum.paris.transactions" "decode_transaction". +Axiom ethereum_paris_transactions_imports_encode_transaction : + IsImported globals "ethereum.paris.transactions" "encode_transaction". + +Axiom ethereum_paris_trie_imports_Trie : + IsImported globals "ethereum.paris.trie" "Trie". +Axiom ethereum_paris_trie_imports_root : + IsImported globals "ethereum.paris.trie" "root". +Axiom ethereum_paris_trie_imports_trie_set : + IsImported globals "ethereum.paris.trie" "trie_set". + +Axiom ethereum_paris_utils_message_imports_prepare_message : + IsImported globals "ethereum.paris.utils.message" "prepare_message". + +Axiom ethereum_paris_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.paris.vm.interpreter" "process_message_call". + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |), + make_tuple [ ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "prev_randao" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_limit" |); + M.get_name (| globals, locals_stack, "parent_gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_target" |), + M.get_name (| globals, locals_stack, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_base_fee_per_gas_in_globals : + IsInGlobals globals "calculate_base_fee_per_gas" (make_function calculate_base_fee_per_gas). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |), + Constant.bytes "0000000000000000" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "prev_randao"; "transactions"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "map" |), + make_list [ + M.get_name (| globals, locals_stack, "decode_transaction" |); + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "encode_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "base_fee_per_gas" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "_address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |), + M.get_name (| globals, locals_stack, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_2930_in_globals : + IsInGlobals globals "signing_hash_2930" (make_function signing_hash_2930). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_1559_in_globals : + IsInGlobals globals "signing_hash_1559" (make_function signing_hash_1559). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/fork_types.md new file mode 100644 index 00000000..529554e9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/simulations/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/simulations/fork_types.md new file mode 100644 index 00000000..55903e1a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/simulations/fork_types.md @@ -0,0 +1,18 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/simulations/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require ethereum.simulations.base_types. + +Module Address. + Inductive t : Set := + | Make (address : base_types.Bytes20.t). + + Definition get (address : t) : base_types.Bytes20.t := + match address with + | Make address => address + end. +End Address. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/simulations/state.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/simulations/state.md new file mode 100644 index 00000000..54d09803 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/simulations/state.md @@ -0,0 +1,11 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/simulations/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Module State. + Parameter t : Set. +End State. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/state.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/state.md new file mode 100644 index 00000000..92fa8e58 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/state.md @@ -0,0 +1,1360 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_paris_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.paris.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_paris_fork_types_imports_Account : + IsImported globals "ethereum.paris.fork_types" "Account". +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". + +Axiom ethereum_paris_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.paris.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_paris_trie_imports_Trie : + IsImported globals "ethereum.paris.trie" "Trie". +Axiom ethereum_paris_trie_imports_copy_trie : + IsImported globals "ethereum.paris.trie" "copy_trie". +Axiom ethereum_paris_trie_imports_root : + IsImported globals "ethereum.paris.trie" "root". +Axiom ethereum_paris_trie_imports_trie_get : + IsImported globals "ethereum.paris.trie" "trie_get". +Axiom ethereum_paris_trie_imports_trie_set : + IsImported globals "ethereum.paris.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom mark_account_created_in_globals : + IsInGlobals globals "mark_account_created" (make_function mark_account_created). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "_" |); M.get_name (| globals, locals_stack, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "original_account_trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "original_value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "original_value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_original_in_globals : + IsInGlobals globals "get_storage_original" (make_function get_storage_original). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/transactions.md new file mode 100644 index 00000000..45eff0bc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/transactions.md @@ -0,0 +1,306 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AccessListTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition FeeMarketTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_transaction_in_globals : + IsInGlobals globals "encode_transaction" (make_function encode_transaction). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom decode_transaction_in_globals : + IsInGlobals globals "decode_transaction" (make_function decode_transaction). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/trie.md new file mode 100644 index 00000000..d08eacf0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/trie.md @@ -0,0 +1,1645 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_gray_glacier_imports_trie : + IsImported globals "ethereum.gray_glacier" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_paris_blocks_imports_Receipt : + IsImported globals "ethereum.paris.blocks" "Receipt". + +Axiom ethereum_paris_fork_types_imports_Account : + IsImported globals "ethereum.paris.fork_types" "Account". +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". +Axiom ethereum_paris_fork_types_imports_encode_account : + IsImported globals "ethereum.paris.fork_types" "encode_account". + +Axiom ethereum_paris_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.paris.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/__init__.md new file mode 100644 index 00000000..51cde751 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/address.md new file mode 100644 index 00000000..7693a75a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this paris version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/hexadecimal.md new file mode 100644 index 00000000..068e5a2f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Paris types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Bloom : + IsImported globals "ethereum.paris.fork_types" "Bloom". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/message.md new file mode 100644 index 00000000..b48f1d3d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/utils/message.md @@ -0,0 +1,278 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_state_imports_get_account : + IsImported globals "ethereum.paris.state" "get_account". + +Axiom ethereum_paris_vm_imports_Environment : + IsImported globals "ethereum.paris.vm" "Environment". +Axiom ethereum_paris_vm_imports_Message : + IsImported globals "ethereum.paris.vm" "Message". + +Axiom ethereum_paris_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.paris.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_paris_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.paris.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, locals_stack, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/__init__.md new file mode 100644 index 00000000..ef8a8372 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/__init__.md @@ -0,0 +1,273 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_state_imports_State : + IsImported globals "ethereum.paris.state" "State". +Axiom ethereum_paris_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.paris.state" "account_exists_and_is_empty". + +Axiom ethereum_paris_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/exceptions.md new file mode 100644 index 00000000..1d8e4750 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/exceptions.md @@ -0,0 +1,181 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidParameter : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidContractPrefix : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/gas.md new file mode 100644 index 00000000..c02b08da --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/gas.md @@ -0,0 +1,938 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/__init__.md new file mode 100644 index 00000000..1f595992 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_paris_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.paris.vm.instructions" "arithmetic". + +Axiom ethereum_paris_vm_instructions_imports_bitwise : + IsImported globals "ethereum.paris.vm.instructions" "bitwise". + +Axiom ethereum_paris_vm_instructions_imports_block : + IsImported globals "ethereum.paris.vm.instructions" "block". + +Axiom ethereum_paris_vm_instructions_imports_comparison : + IsImported globals "ethereum.paris.vm.instructions" "comparison". + +Axiom ethereum_paris_vm_instructions_imports_control_flow : + IsImported globals "ethereum.paris.vm.instructions" "control_flow". + +Axiom ethereum_paris_vm_instructions_imports_environment : + IsImported globals "ethereum.paris.vm.instructions" "environment". + +Axiom ethereum_paris_vm_instructions_imports_keccak : + IsImported globals "ethereum.paris.vm.instructions" "keccak". + +Axiom ethereum_paris_vm_instructions_imports_log : + IsImported globals "ethereum.paris.vm.instructions" "log". + +Axiom ethereum_paris_vm_instructions_imports_memory : + IsImported globals "ethereum.paris.vm.instructions" "memory". + +Axiom ethereum_paris_vm_instructions_imports_stack : + IsImported globals "ethereum.paris.vm.instructions" "stack". + +Axiom ethereum_paris_vm_instructions_imports_storage : + IsImported globals "ethereum.paris.vm.instructions" "storage". + +Axiom ethereum_paris_vm_instructions_imports_system : + IsImported globals "ethereum.paris.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/arithmetic.md new file mode 100644 index 00000000..1b456487 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.paris.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_paris_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.paris.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_paris_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_LOW". +Axiom ethereum_paris_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.paris.vm.gas" "GAS_MID". +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/bitwise.md new file mode 100644 index 00000000..47355449 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/block.md new file mode 100644 index 00000000..c4bc3734 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/block.md @@ -0,0 +1,468 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.paris.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition prev_randao : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "prev_randao" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom prev_randao_in_globals : + IsInGlobals globals "prev_randao" (make_function prev_randao). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom chain_id_in_globals : + IsInGlobals globals "chain_id" (make_function chain_id). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/comparison.md new file mode 100644 index 00000000..2b184f53 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/control_flow.md new file mode 100644 index 00000000..3a2e0523 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.paris.vm.gas" "GAS_HIGH". +Axiom ethereum_paris_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.paris.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_paris_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.paris.vm.gas" "GAS_MID". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.paris.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/environment.md new file mode 100644 index 00000000..ff618af2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/environment.md @@ -0,0 +1,1610 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.paris.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_paris_state_imports_get_account : + IsImported globals "ethereum.paris.state" "get_account". + +Axiom ethereum_paris_utils_address_imports_to_address : + IsImported globals "ethereum.paris.utils.address" "to_address". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". +Axiom ethereum_paris_vm_memory_imports_memory_write : + IsImported globals "ethereum.paris.vm.memory" "memory_write". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_paris_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.paris.vm.gas" "GAS_COPY". +Axiom ethereum_paris_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.paris.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_paris_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.paris.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom self_balance_in_globals : + IsInGlobals globals "self_balance" (make_function self_balance). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom base_fee_in_globals : + IsInGlobals globals "base_fee" (make_function base_fee). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/keccak.md new file mode 100644 index 00000000..0af3cbf0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.paris.vm.gas" "GAS_KECCAK256". +Axiom ethereum_paris_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.paris.vm.memory" "memory_read_bytes". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/log.md new file mode 100644 index 00000000..c1a35cbe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.paris.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_paris_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.paris.vm.gas" "GAS_LOG". +Axiom ethereum_paris_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.paris.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_paris_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.paris.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.paris.vm.memory" "memory_read_bytes". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/memory.md new file mode 100644 index 00000000..e70b6bee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.paris.vm.memory" "memory_read_bytes". +Axiom ethereum_paris_vm_memory_imports_memory_write : + IsImported globals "ethereum.paris.vm.memory" "memory_write". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/proofs/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/proofs/arithmetic.md new file mode 100644 index 00000000..aaa37bdb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/proofs/arithmetic.md @@ -0,0 +1,80 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/proofs/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import proofs.CoqOfPython. +Require Import simulations.CoqOfPython. +Require Import proofs.heap. + +Require ethereum.paris.vm.instructions.simulations.arithmetic. +Require ethereum.paris.vm.instructions.arithmetic. +Require ethereum.paris.vm.stack. + +Require ethereum.simulations.base_types. +Module U256 := base_types.U256. + +Import Run. + +Module Option. + Definition map {A B} (f : A -> B) (x : option A) : option B := + match x with + | Some x => Some (f x) + | None => None + end. +End Option. + +Module AddLocals. + Record t : Set := { + x : option U256.t; + y : option U256.t; + result : option U256.t; + }. + + Definition init : t := + {| + x := None; + y := None; + result := None; + |}. + + (* Definition to_object (locals : t) : Object.t Value.t := + Object.make [ + ("x", Option.map U256.to_value locals.(x)); + ("y", Option.map U256.to_value locals.(y)); + ("result", Option.map U256.to_value locals.(result)) + ]. *) +End AddLocals. + +(* Lemma run_add (stack : Stack.t) (heap : Heap.t) : + let '(result, evm') := simulations.arithmetic.add heap.(Heap.evm) in + let result := + match result with + | inl tt => inl Constant.None_ + | inr exn => inr (Exception.Raise (Some Constant.None_)) + end in + let heap' := heap <| Heap.evm := evm' |> in + exists fresh_stack, + {{ stack, heap | + arithmetic.add (make_list []) (make_dict []) โ‡“ + result + | stack ++ fresh_stack, heap' }}. +Proof. + destruct simulations.arithmetic.add as [result evm'] eqn:?. + unfold arithmetic.add, simulations.arithmetic.add in *. + cbn in *. + eexists. + apply (Run.CallPrimitiveStateAllocStack AddLocals.init AddLocals.to_object); [reflexivity |]. + cbn. + eapply Run.CallPrimitiveStateReadStack. + { now erewrite Stack.read_length_eq. } + { cbn. + eapply Run.CallPrimitiveGetInGlobals. + { apply arithmetic.ethereum_paris_vm_stack_imports_pop. + apply stack.pop_in_globals. + } + { admit. } + } +Admitted. *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/simulations/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/simulations/arithmetic.md new file mode 100644 index 00000000..2f365d23 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/simulations/arithmetic.md @@ -0,0 +1,262 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/simulations/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.CoqOfPython. +Require Import simulations.builtins. + + +Require ethereum.simulations.base_types. +Definition U255_CEIL_VALUE := base_types.U255_CEIL_VALUE. +Module U256 := base_types.U256. +Definition U256_CEIL_VALUE := base_types.U256_CEIL_VALUE. +Module Uint := base_types.Uint. + +Require ethereum.paris.vm.simulations.__init__. +Module Evm := __init__.Evm. + +Require ethereum.paris.vm.simulations.gas. +Definition GAS_EXPONENTIATION := gas.GAS_EXPONENTIATION. +Definition GAS_EXPONENTIATION_PER_BYTE := gas.GAS_EXPONENTIATION_PER_BYTE. +Definition GAS_LOW := gas.GAS_LOW. +Definition GAS_MID := gas.GAS_MID. +Definition GAS_VERY_LOW := gas.GAS_VERY_LOW. +Definition charge_gas := gas.charge_gas. + +Require ethereum.paris.vm.simulations.stack. +Definition pop := stack.pop. +Definition push := stack.push. + +Import simulations.CoqOfPython.Notations. + +(* For sanity checks *) +Axiom environment : __init__.Environment.t. +Axiom message : __init__.Message.t Evm.t. + +Definition empty_evm : Evm.t := + Evm.Make message {| + Evm.Rest.pc := Uint.Make 0; + Evm.Rest.stack := []; + Evm.Rest.memory := []; + Evm.Rest.code := __init__.Bytes.Make []; + Evm.Rest.gas_left := Uint.Make 0; + Evm.Rest.env := environment; + Evm.Rest.valid_jump_destinations := []; + Evm.Rest.logs := []; + Evm.Rest.refund_counter := 0; + Evm.Rest.running := true; + Evm.Rest.output := __init__.Bytes.Make []; + Evm.Rest.accounts_to_delete := []; + Evm.Rest.touched_accounts := []; + Evm.Rest.return_data := __init__.Bytes.Make []; + Evm.Rest.error := None; + Evm.Rest.accessed_addresses := []; + Evm.Rest.accessed_storage_keys := []; + |}. + +Definition evm_with_gas : Evm.t := + Evm.Lens.gas_left.(Lens.write) empty_evm GAS_VERY_LOW. + +Definition evm_with_stack : Evm.t := + Evm.Lens.stack.(Lens.write) evm_with_gas [ + U256.of_Z 23; + U256.of_Z 3; + U256.of_Z 5 + ]. + +Definition wrapped_binary_operation wrapped_operation gas_charge : MS? Evm.t Exception.t unit := + (* STACK *) + letS? x := StateError.lift_lens Evm.Lens.stack pop in + letS? y := StateError.lift_lens Evm.Lens.stack pop in + + (* GAS *) + letS? _ := charge_gas gas_charge in + + (* OPERATION *) + let result := wrapped_operation x y in + + letS? _ := StateError.lift_lens Evm.Lens.stack (push result) in + + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + + returnS? tt. + +Definition add : MS? Evm.t Exception.t unit := + wrapped_binary_operation U256.wrapping_add GAS_VERY_LOW. + +(* Compute add evm_with_stack. *) + +Definition sub : MS? Evm.t Exception.t unit := + wrapped_binary_operation U256.wrapping_sub GAS_VERY_LOW. + +(* Compute sub evm_with_stack. *) + +Definition mul : MS? Evm.t Exception.t unit := + wrapped_binary_operation U256.wrapping_mul GAS_VERY_LOW. + +(* Compute mul evm_with_stack. *) + +Definition div : MS? Evm.t Exception.t unit := + (* STACK *) + letS? divisor := StateError.lift_lens Evm.Lens.stack pop in + letS? divident := StateError.lift_lens Evm.Lens.stack pop in + + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + + (* OPERATION *) + + let division := + match (U256.to_Z divident) with + | 0 => + U256.of_Z 0 + | _ => + U256.of_Z ((U256.to_Z divisor) / (U256.to_Z divident)) + end in + + let result := division in + + letS? _ := StateError.lift_lens Evm.Lens.stack (push result) in + + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + + returnS? tt. + +(* Compute div evm_with_stack. *) + +(* Name collides with Coq's mod. *) + +Definition modulo : MS? Evm.t Exception.t unit := + (* STACK *) + letS? x := StateError.lift_lens Evm.Lens.stack pop in + letS? y := StateError.lift_lens Evm.Lens.stack pop in + + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + + (* OPERATION *) + + let modular y := + match (U256.to_Z y) with + | 0 => + U256.of_Z 0 + | _ => + U256.of_Z ((U256.to_Z x) mod (U256.to_Z y)) + end + in + + let result := modular y in + + letS? _ := StateError.lift_lens Evm.Lens.stack (push result) in + + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + + returnS? tt. + +(* Compute modulo evm_with_stack. *) + +Definition add_mod : MS? Evm.t Exception.t unit := + (* STACK *) + letS? x := StateError.lift_lens Evm.Lens.stack pop in + letS? y := StateError.lift_lens Evm.Lens.stack pop in + letS? z := StateError.lift_lens Evm.Lens.stack pop in + + (* GAS *) + letS? _ := charge_gas GAS_MID in + + (* OPERATION *) + + let addition_modular y := + match (U256.to_Z y) with + | 0 => + U256.of_Z 0 + | _ => + U256.of_Z (((U256.to_Z x) + (U256.to_Z y)) mod (U256.to_Z z)) + end + in + + let result := addition_modular y in + + letS? _ := StateError.lift_lens Evm.Lens.stack (push result) in + + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + + returnS? tt. + +(* Compute add_mod evm_with_stack. *) + +Definition mul_mod : MS? Evm.t Exception.t unit := + (* STACK *) + letS? x := StateError.lift_lens Evm.Lens.stack pop in + letS? y := StateError.lift_lens Evm.Lens.stack pop in + letS? z := StateError.lift_lens Evm.Lens.stack pop in + + (* GAS *) + letS? _ := charge_gas GAS_MID in + + (* OPERATION *) + + let multiplication_modular y := + match (U256.to_Z y) with + | 0 => + U256.of_Z 0 + | _ => + U256.of_Z (((U256.to_Z x) * (U256.to_Z y)) mod (U256.to_Z z)) + end + in + + let result := multiplication_modular y in + + letS? _ := StateError.lift_lens Evm.Lens.stack (push result) in + + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + + returnS? tt. + + +(* Compute mul_mod evm_with_stack. *) + +(* "This is equivalent to 1 + floor(log(y, 256))" *) + +Definition byte_length n := + 1 + Z.log2(n) / 8. + +Definition exp : MS? Evm.t Exception.t unit := + (* STACK *) + letS? base := StateError.lift_lens Evm.Lens.stack pop in + letS? exponent := StateError.lift_lens Evm.Lens.stack pop in + + let exponent_bytes := byte_length (U256.to_Z exponent) in + (* GAS *) + letS? _ := charge_gas (gas.Uint.Make + ((gas.Uint.get GAS_EXPONENTIATION) + + (gas.Uint.get GAS_EXPONENTIATION_PER_BYTE) + * exponent_bytes)) in + + (* OPERATION *) + + let result := U256.of_Z ((Z.pow (U256.to_Z base) (U256.to_Z exponent)) mod U256_CEIL_VALUE) in + + + letS? _ := StateError.lift_lens Evm.Lens.stack (push result) in + + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + + returnS? tt. + +(* Compute exp evm_with_stack. *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/simulations/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/simulations/bitwise.md new file mode 100644 index 00000000..879c0d5b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/simulations/bitwise.md @@ -0,0 +1,375 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/simulations/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.CoqOfPython. +Require Import simulations.builtins. + +Require ethereum.simulations.base_types. +Definition U255_CEIL_VALUE := base_types.U255_CEIL_VALUE. +Module U256 := base_types.U256. +Definition U256_CEIL_VALUE := base_types.U256_CEIL_VALUE. +Module Uint := base_types.Uint. + +Require ethereum.paris.vm.simulations.__init__. +Module Evm := __init__.Evm. + +Require ethereum.paris.vm.simulations.gas. +Definition GAS_EXPONENTIATION := gas.GAS_EXPONENTIATION. +Definition GAS_EXPONENTIATION_PER_BYTE := gas.GAS_EXPONENTIATION_PER_BYTE. +Definition GAS_LOW := gas.GAS_LOW. +Definition GAS_MID := gas.GAS_MID. +Definition GAS_VERY_LOW := gas.GAS_VERY_LOW. +Definition charge_gas := gas.charge_gas. + +Require ethereum.paris.vm.simulations.stack. +Definition pop := stack.pop. +Definition push := stack.push. + +Import simulations.CoqOfPython.Notations. +(* +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + # GAS + charge_gas(evm, GAS_VERY_LOW) + # OPERATION + push(evm.stack, x & y) + # PROGRAM COUNTER + evm.pc += 1 +*) +Definition bitwise_and : MS? Evm.t Exception.t unit := + (* STACK *) + letS? x := StateError.lift_lens Evm.Lens.stack pop in + letS? y := StateError.lift_lens Evm.Lens.stack pop in + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + (* OPERATION *) + letS? _ := StateError.lift_lens Evm.Lens.stack ( + push (U256.bit_and x y)) in + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + returnS? tt. + +(* +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 +*) +Definition bitwise_or : MS? Evm.t Exception.t unit := + (* STACK *) + letS? x := StateError.lift_lens Evm.Lens.stack pop in + letS? y := StateError.lift_lens Evm.Lens.stack pop in + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + (* OPERATION *) + letS? _ := StateError.lift_lens Evm.Lens.stack ( + push (U256.bit_or x y)) in + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + returnS? tt. + +(* +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 +*) +Definition bitwise_xor : MS? Evm.t Exception.t unit := + (* STACK *) + letS? x := StateError.lift_lens Evm.Lens.stack pop in + letS? y := StateError.lift_lens Evm.Lens.stack pop in + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + (* OPERATION *) + letS? _ := StateError.lift_lens Evm.Lens.stack ( + push (U256.bit_xor x y)) in + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + returnS? tt. + +(* +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 +*) +Definition bitwise_not : MS? Evm.t Exception.t unit := + (* STACK *) + letS? x := StateError.lift_lens Evm.Lens.stack pop in + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + (* OPERATION *) + letS? _ := StateError.lift_lens Evm.Lens.stack ( + push (U256.bit_not x)) in + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + returnS? tt. + +(* +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +*) +Definition get_byte : MS? Evm.t Exception.t unit := + (* STACK *) + letS? byte_index := StateError.lift_lens Evm.Lens.stack pop in + letS? word := StateError.lift_lens Evm.Lens.stack pop in + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + (* OPERATION *) + let result := + if ((U256.to_Z byte_index)>=? 32) + then (U256.of_Z 0) + else( + let extra_bytes_to_right := 31 - (U256.to_Z byte_index)%Z in + let word := (Z.shiftr (U256.to_Z word) (extra_bytes_to_right * 8)) in + let word := Z.land word (0XFF%Z) in + (U256.of_Z word) + ) + in + letS? _ := StateError.lift_lens Evm.Lens.stack ( + push result) in + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + returnS? tt. + +(* def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 *) +Definition bitwise_shl : MS? Evm.t Exception.t unit := + (* STACK *) + letS? shift := StateError.lift_lens Evm.Lens.stack pop in + letS? value := StateError.lift_lens Evm.Lens.stack pop in + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + (* OPERATION *) + let result := + if (U256.to_Z shift) + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + returnS? tt. + +(* def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 *) +Definition bitwise_shr : MS? Evm.t Exception.t unit := + (* STACK *) + letS? shift := StateError.lift_lens Evm.Lens.stack pop in + letS? value := StateError.lift_lens Evm.Lens.stack pop in + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + (* OPERATION *) + let result := + if (U256.to_Z shift) + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + returnS? tt. + +(* +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 *) +Definition bitwise_sar : MS? Evm.t Exception.t unit := + (* STACK *) + letS? shift := StateError.lift_lens Evm.Lens.stack pop in + letS? signed_value := StateError.lift_lens Evm.Lens.stack pop in + (* GAS *) + letS? _ := charge_gas GAS_VERY_LOW in + (* OPERATION *) + let result := + if (U256.to_Z shift) =? 0) + then (U256.of_Z 0) + else U256.MAX_VALUE) in + letS? _ := StateError.lift_lens Evm.Lens.stack (push result) in + (* PROGRAM COUNTER *) + letS? _ := StateError.lift_lens Evm.Lens.pc (fun pc => + (inl tt, Uint.__add__ pc (Uint.Make 1))) in + returnS? tt. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/stack.md new file mode 100644 index 00000000..6ff85270 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". +Axiom ethereum_paris_vm_imports_stack : + IsImported globals "ethereum.paris.vm" "stack". + +Axiom ethereum_paris_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.paris.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/storage.md new file mode 100644 index 00000000..c083ecdb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/storage.md @@ -0,0 +1,512 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_state_imports_get_storage : + IsImported globals "ethereum.paris.state" "get_storage". +Axiom ethereum_paris_state_imports_get_storage_original : + IsImported globals "ethereum.paris.state" "get_storage_original". +Axiom ethereum_paris_state_imports_set_storage : + IsImported globals "ethereum.paris.state" "set_storage". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfGasError". +Axiom ethereum_paris_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.paris.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_paris_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.paris.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_paris_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.paris.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_paris_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.paris.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_paris_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.paris.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_paris_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.paris.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_paris_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/system.md new file mode 100644 index 00000000..89ced28d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/instructions/system.md @@ -0,0 +1,2276 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.paris.state" "account_exists_and_is_empty". +Axiom ethereum_paris_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.paris.state" "account_has_code_or_nonce". +Axiom ethereum_paris_state_imports_get_account : + IsImported globals "ethereum.paris.state" "get_account". +Axiom ethereum_paris_state_imports_increment_nonce : + IsImported globals "ethereum.paris.state" "increment_nonce". +Axiom ethereum_paris_state_imports_is_account_alive : + IsImported globals "ethereum.paris.state" "is_account_alive". +Axiom ethereum_paris_state_imports_set_account_balance : + IsImported globals "ethereum.paris.state" "set_account_balance". + +Axiom ethereum_paris_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.paris.utils.address" "compute_contract_address". +Axiom ethereum_paris_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.paris.utils.address" "compute_create2_contract_address". +Axiom ethereum_paris_utils_address_imports_to_address : + IsImported globals "ethereum.paris.utils.address" "to_address". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". +Axiom ethereum_paris_vm_imports_Message : + IsImported globals "ethereum.paris.vm" "Message". +Axiom ethereum_paris_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.paris.vm" "incorporate_child_on_error". +Axiom ethereum_paris_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.paris.vm" "incorporate_child_on_success". + +Axiom ethereum_paris_vm_exceptions_imports_Revert : + IsImported globals "ethereum.paris.vm.exceptions" "Revert". +Axiom ethereum_paris_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.paris.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_paris_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.paris.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_paris_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_paris_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.paris.vm.gas" "GAS_CREATE". +Axiom ethereum_paris_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_paris_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.paris.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_paris_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.paris.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_paris_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.paris.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_paris_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_paris_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.paris.vm.gas" "GAS_ZERO". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.paris.vm.gas" "calculate_message_call_gas". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". +Axiom ethereum_paris_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.paris.vm.gas" "max_message_call_gas". + +Axiom ethereum_paris_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.paris.vm.memory" "memory_read_bytes". +Axiom ethereum_paris_vm_memory_imports_memory_write : + IsImported globals "ethereum.paris.vm.memory" "memory_write". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "beneficiary" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/interpreter.md new file mode 100644 index 00000000..fdfa07fc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/interpreter.md @@ -0,0 +1,697 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.paris.state" "account_exists_and_is_empty". +Axiom ethereum_paris_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.paris.state" "account_has_code_or_nonce". +Axiom ethereum_paris_state_imports_begin_transaction : + IsImported globals "ethereum.paris.state" "begin_transaction". +Axiom ethereum_paris_state_imports_commit_transaction : + IsImported globals "ethereum.paris.state" "commit_transaction". +Axiom ethereum_paris_state_imports_destroy_storage : + IsImported globals "ethereum.paris.state" "destroy_storage". +Axiom ethereum_paris_state_imports_increment_nonce : + IsImported globals "ethereum.paris.state" "increment_nonce". +Axiom ethereum_paris_state_imports_mark_account_created : + IsImported globals "ethereum.paris.state" "mark_account_created". +Axiom ethereum_paris_state_imports_move_ether : + IsImported globals "ethereum.paris.state" "move_ether". +Axiom ethereum_paris_state_imports_rollback_transaction : + IsImported globals "ethereum.paris.state" "rollback_transaction". +Axiom ethereum_paris_state_imports_set_code : + IsImported globals "ethereum.paris.state" "set_code". +Axiom ethereum_paris_state_imports_touch_account : + IsImported globals "ethereum.paris.state" "touch_account". + +Axiom ethereum_paris_vm_imports_Message : + IsImported globals "ethereum.paris.vm" "Message". + +Axiom ethereum_paris_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.paris.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.paris.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_paris_vm_imports_Environment : + IsImported globals "ethereum.paris.vm" "Environment". +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.paris.vm.exceptions" "AddressCollision". +Axiom ethereum_paris_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.paris.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_paris_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.paris.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_paris_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.paris.vm.exceptions" "InvalidOpcode". +Axiom ethereum_paris_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfGasError". +Axiom ethereum_paris_vm_exceptions_imports_Revert : + IsImported globals "ethereum.paris.vm.exceptions" "Revert". +Axiom ethereum_paris_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.paris.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_paris_vm_instructions_imports_Ops : + IsImported globals "ethereum.paris.vm.instructions" "Ops". +Axiom ethereum_paris_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.paris.vm.instructions" "op_implementation". + +Axiom ethereum_paris_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.paris.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/memory.md new file mode 100644 index 00000000..76ab6aee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..868594c6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/__init__.md @@ -0,0 +1,124 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_paris_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.paris.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..2c215f84 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". + +Axiom ethereum_paris_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..1c7c87b0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,144 @@ +# ๐Ÿ“ blake2f.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/precompiled_contracts/blake2f.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.precompiled_contracts.blake2f". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.paris.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.paris.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, locals_stack, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, locals_stack, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, locals_stack, "rounds" |); + M.get_name (| globals, locals_stack, "h" |); + M.get_name (| globals, locals_stack, "m" |); + M.get_name (| globals, locals_stack, "t_0" |); + M.get_name (| globals, locals_stack, "t_1" |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom blake2f_in_globals : + IsInGlobals globals "blake2f" (make_function blake2f). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..04e674c5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.paris.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..5d1268b3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.paris.vm.gas" "GAS_IDENTITY". +Axiom ethereum_paris_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..69adc720 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/mapping.md @@ -0,0 +1,80 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_paris_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.paris.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_paris_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.paris.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_paris_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.paris.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_paris_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.paris.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_paris_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.paris.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_paris_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.paris.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_paris_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.paris.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_paris_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.paris.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_paris_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.paris.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..62c068f3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/modexp.md @@ -0,0 +1,700 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |); + M.get_name (| globals, locals_stack, "exp_length" |); + M.get_name (| globals, locals_stack, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Axiom complexity_in_globals : + IsInGlobals globals "complexity" (make_function complexity). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, locals_stack, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, locals_stack, "length_part" |), + M.get_name (| globals, locals_stack, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "count" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom iterations_in_globals : + IsInGlobals globals "iterations" (make_function iterations). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, locals_stack, "complexity" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, locals_stack, "iterations" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |); + M.get_name (| globals, locals_stack, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "multiplication_complexity" |), + M.get_name (| globals, locals_stack, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom gas_cost_in_globals : + IsInGlobals globals "gas_cost" (make_function gas_cost). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..2c7d719f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.paris.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_paris_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..3d1330e3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.paris.vm.gas" "GAS_SHA256". +Axiom ethereum_paris_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/runtime.md new file mode 100644 index 00000000..ddf5cdcb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_vm_instructions_imports_Ops : + IsImported globals "ethereum.paris.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/__init__.md new file mode 100644 index 00000000..d5063856 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/__init__.md @@ -0,0 +1,125 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/simulations/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.CoqOfPython. + +Require ethereum.simulations.base_types. +Module U64 := base_types.U64. +Module U256 := base_types.U256. +Module Bytes := base_types.Bytes. +Module Bytes0 := base_types.Bytes0. +Module Bytes32 := base_types.Bytes32. +Module Uint := base_types.Uint. + +Require ethereum.crypto.simulations.hash. +Module Hash32 := hash.Hash32. + +Require ethereum.paris.simulations.fork_types. +Module Address := fork_types.Address. + +Require ethereum.paris.simulations.state. +Module State := state.State. + +Module Environment. + Record t : Set := { + caller : Address.t; + block_hashes : list Hash32.t; + origin : Address.t; + coinbase : Address.t; + number : Uint.t; + base_fee_per_gas : Uint.t; + gas_limit : Uint.t; + gas_price : Uint.t; + time : U256.t; + prev_randao : Bytes32.t; + state : State.t; + chain_id : U64.t; + traces : list unit + }. +End Environment. + +Module Message. + (** We parametrize this type by the environment. *) + Record t {Evm : Set} : Set := { + caller : Address.t; + target : Bytes0.t + Address.t; + current_target : Address.t; + gas : Uint.t; + value : U256.t; + data : Bytes.t; + code_address : option Address.t; + code : Bytes.t; + depth : Uint.t; + should_transfer_value : bool; + is_static : bool; + accessed_addresses : list Address.t; + accessed_storage_keys : list (Address.t * Bytes32.t); + parent_evm : option Evm + }. + Arguments t : clear implicits. +End Message. + +Module Evm. + (** We split the record as it is recursive in the [message] field, and we cannot have recursive + records. *) + Module Rest. + Record t : Set := { + pc : Uint.t; + stack : list (U256.t); + memory : list ascii; + code : Bytes.t; + gas_left : Uint.t; + env : Environment.t; + valid_jump_destinations : list Uint.t; + logs : list unit; + refund_counter : Z; + running : bool; + output : Bytes.t; + accounts_to_delete : list Address.t; + touched_accounts : list Address.t; + return_data : Bytes.t; + error : option Exception.t; + accessed_addresses : list Address.t; + accessed_storage_keys : list (Address.t * Bytes32.t) + }. + End Rest. + + Inductive t : Set := + | Make (message : Message.t t) (rest : Rest.t). + + Module Lens. + Definition message : Lens.t t (Message.t t) := {| + Lens.read '(Make message _) := message; + Lens.write '(Make _ rest) message := Make message rest; + |}. + + Definition pc : Lens.t t Uint.t := {| + Lens.read '(Make _ rest) := rest.(Rest.pc); + Lens.write '(Make message rest) pc := Make message rest<|Rest.pc := pc|>; + |}. + + Definition stack : Lens.t t (list U256.t) := {| + Lens.read '(Make _ rest) := rest.(Rest.stack); + Lens.write '(Make message rest) stack := Make message rest<|Rest.stack := stack|>; + |}. + + Definition memory : Lens.t t (list ascii) := {| + Lens.read '(Make _ rest) := rest.(Rest.memory); + Lens.write '(Make message rest) memory := Make message rest<|Rest.memory := memory|>; + |}. + + Definition code : Lens.t t Bytes.t := {| + Lens.read '(Make _ rest) := rest.(Rest.code); + Lens.write '(Make message rest) code := Make message rest<|Rest.code := code|>; + |}. + + Definition gas_left : Lens.t t Uint.t := {| + Lens.read '(Make _ rest) := rest.(Rest.gas_left); + Lens.write '(Make message rest) gas_left := Make message rest<|Rest.gas_left := gas_left|>; + |}. + End Lens. +End Evm. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/exceptions.md new file mode 100644 index 00000000..c099f236 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/exceptions.md @@ -0,0 +1,26 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/simulations/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Module ExceptionalHalt. + Inductive t : Set := + | StackUnderflowError + | StackOverflowError + | OutOfGasError + | InvalidOpcode (code : Z) + | InvalidJumpDestError + | StackDepthLimitError + | WriteInStaticContext + | OutOfBoundsRead + | InvalidParameter + | InvalidContractPrefix + | AddressCollision. +End ExceptionalHalt. + +Module Revert. + Inductive t : Set :=. +End Revert. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/gas.md new file mode 100644 index 00000000..77c44445 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/gas.md @@ -0,0 +1,61 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/simulations/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.CoqOfPython. +Require Import simulations.builtins. + +Require ethereum.simulations.base_types. +Module U256 := base_types.U256. +Module Uint := base_types.Uint. + +Require ethereum.paris.vm.simulations.__init__. +Module Evm := __init__.Evm. + +Import simulations.CoqOfPython.Notations. + +Definition GAS_JUMPDEST := Uint.Make 1. +Definition GAS_BASE := Uint.Make 2. +Definition GAS_VERY_LOW := Uint.Make 3. +Definition GAS_STORAGE_SET := Uint.Make 20000. +Definition GAS_STORAGE_UPDATE := Uint.Make 5000. +Definition GAS_STORAGE_CLEAR_REFUND := Uint.Make 4800. +Definition GAS_LOW := Uint.Make 5. +Definition GAS_MID := Uint.Make 8. +Definition GAS_HIGH := Uint.Make 10. +Definition GAS_EXPONENTIATION := Uint.Make 10. +Definition GAS_EXPONENTIATION_PER_BYTE := Uint.Make 50. +Definition GAS_MEMORY := Uint.Make 3. +Definition GAS_KECCAK256 := Uint.Make 30. +Definition GAS_KECCAK256_WORD := Uint.Make 6. +Definition GAS_COPY := Uint.Make 3. +Definition GAS_BLOCK_HASH := Uint.Make 20. +Definition GAS_LOG := Uint.Make 375. +Definition GAS_LOG_DATA := Uint.Make 8. +Definition GAS_LOG_TOPIC := Uint.Make 375. +Definition GAS_CREATE := Uint.Make 32000. +Definition GAS_CODE_DEPOSIT := Uint.Make 200. +Definition GAS_ZERO := Uint.Make 0. +Definition GAS_NEW_ACCOUNT := Uint.Make 25000. +Definition GAS_CALL_VALUE := Uint.Make 9000. +Definition GAS_CALL_STIPEND := Uint.Make 2300. +Definition GAS_SELF_DESTRUCT := Uint.Make 5000. +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT := Uint.Make 25000. +Definition GAS_ECRECOVER := Uint.Make 3000. +Definition GAS_SHA256 := Uint.Make 60. +Definition GAS_SHA256_WORD := Uint.Make 12. +Definition GAS_RIPEMD160 := Uint.Make 600. +Definition GAS_RIPEMD160_WORD := Uint.Make 120. +Definition GAS_IDENTITY := Uint.Make 15. +Definition GAS_IDENTITY_WORD := Uint.Make 3. +Definition GAS_RETURN_DATA_COPY := Uint.Make 3. +Definition GAS_FAST_STEP := Uint.Make 5. +Definition GAS_BLAKE2_PER_ROUND := Uint.Make 1. +Definition GAS_COLD_SLOAD := Uint.Make 2100. +Definition GAS_COLD_ACCOUNT_ACCESS := Uint.Make 2600. +Definition GAS_WARM_ACCESS := Uint.Make 100. + +Parameter charge_gas : forall (amount : Uint.t), MS? Evm.t Exception.t unit. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/__init__.md new file mode 100644 index 00000000..c149aae0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/__init__.md @@ -0,0 +1,40 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/simulations/proofs/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.CoqOfPython. +Require Import simulations.proofs.CoqOfPython. +Require Import simulations.proofs.heap. + +Require Import ethereum.paris.vm.simulations.__init__. + +Require ethereum.simulations.proofs.base_types. +Module Uint := base_types.Uint. +Module U256 := base_types.U256. + +Definition globals : Globals.t := "ethereum.paris.vm". + +Module Evm. + Definition stack_to_value : Value.t := + Value.Make "builtins" "list" (Pointer.heap + Address.stack + (fun (stack : list U256.t) => + Object.wrapper (Data.List (List.map U256.to_value stack)) + ) + ). + + Definition to_value : Value.t := + Value.Make globals "Evm" (Pointer.heap + Address.evm + (fun (evm : Heap.Evm.t) => + Object.make [ + ("pc", Uint.to_value evm.(Heap.Evm.pc)); + ("stack", stack_to_value); + ("gas_left", Uint.to_value evm.(Heap.Evm.gas_left)) + ] + ) + ). +End Evm. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/exceptions.md new file mode 100644 index 00000000..0aaa4896 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/exceptions.md @@ -0,0 +1,41 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/simulations/proofs/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.proofs.CoqOfPython. +Require Import simulations.proofs.heap. + +Require Import ethereum.paris.vm.simulations.exceptions. + +Import Run. + +Module ExceptionalHalt. + Definition to_value (exn : ExceptionalHalt.t) : Value.t := + match exn with + | ExceptionalHalt.StackUnderflowError => + Value.Make "exceptions" "StackUnderflowError" (Pointer.Imm Object.empty) + | ExceptionalHalt.StackOverflowError => + Value.Make "exceptions" "StackOverflowError" (Pointer.Imm Object.empty) + | ExceptionalHalt.OutOfGasError => + Value.Make "exceptions" "OutOfGasError" (Pointer.Imm Object.empty) + | ExceptionalHalt.InvalidOpcode code => + Value.Make "exceptions" "InvalidOpcode" (Pointer.Imm (Object.wrapper (Data.Integer code))) + | ExceptionalHalt.InvalidJumpDestError => + Value.Make "exceptions" "InvalidJumpDestError" (Pointer.Imm Object.empty) + | ExceptionalHalt.StackDepthLimitError => + Value.Make "exceptions" "StackDepthLimitError" (Pointer.Imm Object.empty) + | ExceptionalHalt.WriteInStaticContext => + Value.Make "exceptions" "WriteInStaticContext" (Pointer.Imm Object.empty) + | ExceptionalHalt.OutOfBoundsRead => + Value.Make "exceptions" "OutOfBoundsRead" (Pointer.Imm Object.empty) + | ExceptionalHalt.InvalidParameter => + Value.Make "exceptions" "InvalidParameter" (Pointer.Imm Object.empty) + | ExceptionalHalt.InvalidContractPrefix => + Value.Make "exceptions" "InvalidContractPrefix" (Pointer.Imm Object.empty) + | ExceptionalHalt.AddressCollision => + Value.Make "exceptions" "AddressCollision" (Pointer.Imm Object.empty) + end. +End ExceptionalHalt. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/stack.md new file mode 100644 index 00000000..1b4fc277 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/proofs/stack.md @@ -0,0 +1,190 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/simulations/proofs/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.proofs.CoqOfPython. +Require Import simulations.proofs.heap. + +Require ethereum.paris.vm.simulations.stack. +Require ethereum.paris.vm.stack. +Require CoqOfPython.builtins. + +Require ethereum.paris.vm.simulations.proofs.__init__. +Require simulations.proofs.builtins. + +Module Evm := __init__.Evm. + +Import Run. + +Module PopLocals. + Record t : Set := { + (* The stack is a pointer to some data in the heap. *) + stack : unit; + }. + + Definition init (evm : Evm.t) : t := + {| + stack := tt; + |}. + + Definition to_object (locals : t) : Object.t Value.t := + Object.make_option [ + ("stack", Some Evm.stack_to_value) + ]. +End PopLocals. + +(** Test function to experiment with the simulations. We might remove it later. *) +Definition get_length : Value.t -> Value.t -> M := + let globals := "ethereum.paris.vm.stack" in + let locals_stack := [] in + + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + M.catch_return ltac:(M.monadic ( + let _ := Constant.str " + Returns the length of the stack. + + Parameters + ---------- + evm : + EVM stack. + + Returns + ------- + length : `int` + Length of the stack. + + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +(** Run for the function [get_length]. *) +Definition run_get_length (stack : Stack.t) (heap : Heap.t) : + {{ stack, heap | + stack.get_length (make_list [Evm.stack_to_value]) (make_dict []) โ‡“ + (fun (n : Z) => inl (Constant.int n)) + | + fun stack' => stack' = stack, + fun heap' => heap' = heap + }}. +Proof. + cbn. + apply Run.CallPrimitiveStateAllocImm. + cbn. + eapply Run.CallPrimitiveGetInGlobals. { + apply builtins_is_imported. + apply builtins.len_in_globals. + } + cbn. + eapply Run.CallClosure. { + eapply builtins.run_len. + { pose proof (H := IsRead.Heap stack heap Address.stack). + now apply H. + } + { reflexivity. } + } + intros. + cbn. + now eapply Run.Pure. +Defined. + +(** Very simple version of the function [get_length], that actually only return the length of the + stack. *) +Definition simple_get_length (heap : Heap.t) : Z := + Z.of_nat (List.length heap.(Heap.stack)). + +(** We can show that it only returns the length of the stack by reflexivity! *) +Lemma simple_get_length_eq stack heap : + simple_get_length heap = + let '(l, _, _) := evaluate (run_get_length stack heap) in + l. +Proof. + reflexivity. +Qed. + +(** Test module for demo purposes that could be removed later. *) +Module TestGetLength. + (** Dummy value used for the compute below. *) + Definition dummy_heap : Heap.t := {| + Heap.evm := {| + Heap.Evm.pc := Uint.Make 12; + Heap.Evm.gas_left := Uint.Make 23; + |}; + Heap.stack := [ + U256.of_Z 42; + U256.of_Z 43; + U256.of_Z 44 + ]; + |}. + + Definition current_length : Z := + let '(l, _, _) := evaluate (run_get_length [] dummy_heap) in + l. + + (* Should return 3 *) + (* Compute current_length. *) +End TestGetLength. + +(** Run of the [pop] function. *) +Definition run_pop (stack : Stack.t) (heap : Heap.t) : + {{ stack, heap | + stack.pop (make_list [Evm.stack_to_value]) (make_dict []) โ‡“ + (fun (result : unit + builtins.Exception.t) => + match result with + | inl tt => inl Constant.None_ + | inr exn => inr (Exception.Raise (Some (builtins.Exception.to_value exn))) + end) + | + fun stack' => exists fresh_stack, stack' = stack ++ fresh_stack, + fun heap' => True + }}. +Proof. + cbn. + apply Run.CallPrimitiveStateAllocImm. + cbn. + eapply Run.CallPrimitiveGetInGlobals. { + apply builtins_is_imported. + apply builtins.len_in_globals. + } + cbn. + eapply Run.CallClosure. { + eapply builtins.run_len. + { pose proof (H := IsRead.Heap stack heap Address.stack). + now apply H. + } + { reflexivity. } + } + intros. + cbn. + replace (Compare.eq (Constant.int value_inter) (Constant.int 0)) + with (M.pure (Constant.bool (value_inter =? 0))) + by admit. + cbn. + match goal with + | |- context [ M.if_then_else (Constant.bool ?cond) ] => + replace (M.if_then_else (Constant.bool cond)) + with (fun (success error : M) => if cond then success else error) + by admit + end. + destruct (_ =? _); cbn. + { admit. } + { eapply Run.CallPrimitiveStateRead. { + pose proof (H2 := IsRead.Heap stack_inter heap_inter Address.stack). + now apply H2. + } + cbn. + (* TODO: implement method calls *) + admit. + } +Admitted. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/stack.md new file mode 100644 index 00000000..99e09ca2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/simulations/stack.md @@ -0,0 +1,41 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/simulations/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.CoqOfPython. +Require Import simulations.builtins. + +Require Import simulations.base_types. +Module U256 := base_types.U256. + +Import simulations.CoqOfPython.Notations. + +Definition pop : MS? (list U256.t) Exception.t U256.t := + fun stack => + match stack with + | [] => + ( + inr (Exception.EthereumException ( + exceptions.EthereumException.ExceptionalHalt + exceptions.ExceptionalHalt.StackUnderflowError + )), + stack + ) + | x :: rest => (inl x, rest) + end. + +Definition push (value : U256.t) : MS? (list U256.t) Exception.t unit := + fun stack => + if Z.of_nat (List.length stack) =? 1024 then + ( + inr (Exception.EthereumException ( + exceptions.EthereumException.ExceptionalHalt + exceptions.ExceptionalHalt.StackOverflowError + )), + stack + ) + else + (inl tt, value :: stack). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/stack.md new file mode 100644 index 00000000..317ca754 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/paris/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/paris/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.paris.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_paris_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.paris.vm.exceptions" "StackOverflowError". +Axiom ethereum_paris_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.paris.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/rlp.md b/docs/revm-python-spec/revm-verif/spec-coq/rlp.md new file mode 100644 index 00000000..51b40f6d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/rlp.md @@ -0,0 +1,2600 @@ +# ๐Ÿ“ rlp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/./rlp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.rlp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +.. _rlp: + +Recursive Length Prefix (RLP) Encoding +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Defines the serialization and deserialization format used throughout Ethereum. +". + +Axiom dataclasses_imports_astuple : + IsImported globals "dataclasses" "astuple". +Axiom dataclasses_imports_fields : + IsImported globals "dataclasses" "fields". +Axiom dataclasses_imports_is_dataclass : + IsImported globals "dataclasses" "is_dataclass". + +Axiom typing_imports_Any : + IsImported globals "typing" "Any". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_exceptions_imports_RLPDecodingError : + IsImported globals "ethereum.exceptions" "RLPDecodingError". +Axiom ethereum_exceptions_imports_RLPEncodingError : + IsImported globals "ethereum.exceptions" "RLPEncodingError". + +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_FixedBytes : + IsImported globals "ethereum.base_types" "FixedBytes". +Axiom ethereum_base_types_imports_FixedUint : + IsImported globals "ethereum.base_types" "FixedUint". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition RLP : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Any" |) +)). + +Definition encode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |); + make_tuple [ M.get_name (| globals, locals_stack, "bytearray" |); M.get_name (| globals, locals_stack, "bytes" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |); + make_tuple [ M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "FixedUint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "raw_data" |), "to_be_bytes" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |); + M.get_name (| globals, locals_stack, "str" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "raw_data" |), "encode" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |); + M.get_name (| globals, locals_stack, "bool" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "raw_data" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_bytes" |), + make_list [ + Constant.bytes "01" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |); + M.get_name (| globals, locals_stack, "Sequence" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_sequence" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "is_dataclass" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "astuple" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "RLPEncodingError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "RLP Encoding of type {} is not supported", "format" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_in_globals : + IsInGlobals globals "encode" (make_function encode). + +Definition encode_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "len_raw_data" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "len_raw_data" |), + Constant.int 1 + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "raw_bytes" |), + Constant.int 0 + |), + Constant.int 128 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "raw_bytes" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "len_raw_data" |), + Constant.int 56 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + make_list [ + BinOp.add (| + Constant.int 128, + M.get_name (| globals, locals_stack, "len_raw_data" |) + |) + ] + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "raw_bytes" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "len_raw_data_as_be" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "len_raw_data" |), "to_be_bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + BinOp.add (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + make_list [ + BinOp.add (| + Constant.int 183, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "len_raw_data_as_be" |) + ], + make_dict [] + |) + |) + ] + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "len_raw_data_as_be" |) + |), + M.get_name (| globals, locals_stack, "raw_bytes" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_bytes_in_globals : + IsInGlobals globals "encode_bytes" (make_function encode_bytes). + +Definition encode_sequence : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_sequence" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "joined_encodings" , + M.call (| + M.get_name (| globals, locals_stack, "get_joined_encodings" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_sequence" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "len_joined_encodings" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "joined_encodings" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "len_joined_encodings" |), + Constant.int 56 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.add (| + Constant.int 192, + M.get_name (| globals, locals_stack, "len_joined_encodings" |) + |) + ] + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "joined_encodings" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "len_joined_encodings_as_be" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "len_joined_encodings" |), "to_be_bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + BinOp.add (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.add (| + Constant.int 247, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "len_joined_encodings_as_be" |) + ], + make_dict [] + |) + |) + ] + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "len_joined_encodings_as_be" |) + |), + M.get_name (| globals, locals_stack, "joined_encodings" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_sequence_in_globals : + IsInGlobals globals "encode_sequence" (make_function encode_sequence). + +Definition get_joined_encodings : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_sequence" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| Constant.bytes "", "join" |), + make_list [ + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom get_joined_encodings_in_globals : + IsInGlobals globals "get_joined_encodings" (make_function get_joined_encodings). + +Definition decode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "encoded_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_data" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "RLPDecodingError" |), + make_list [ + Constant.str "Cannot decode empty bytestring" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_data" |), + Constant.int 0 + |), + Constant.int 191 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "decode_to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "decode_to_sequence" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom decode_in_globals : + IsInGlobals globals "decode" (make_function decode). + +Definition T : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "T" + ], + make_dict [] + |) +)). + +Definition decode_to : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "encoded_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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[T]` + The type to decode to. + encoded_data : + A sequence of bytes, in RLP form. + + Returns + ------- + decoded_data : `T` + Object decoded from `encoded_data`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "_decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + M.call (| + M.get_name (| globals, locals_stack, "decode" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom decode_to_in_globals : + IsInGlobals globals "decode_to" (make_function decode_to). + +Definition _decode_to : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "cls"; "raw_rlp" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decode the rlp structure in `encoded_data` to an object of type `cls`. + `cls` can be a `Bytes` subclass, a dataclass, `Uint`, `U256`, + `Tuple[cls, ...]`, `Tuple[cls1, cls2]` or `Union[Bytes, cls]`. + + Parameters + ---------- + cls: `Type[T]` + The type to decode to. + raw_rlp : + A decoded rlp structure. + + Returns + ------- + decoded_data : `T` + Object decoded from `encoded_data`. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "Tuple" |), + make_tuple [ M.get_name (| globals, locals_stack, "Uint" |); Constant.ellipsis ] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "_name" |), + Constant.str "Tuple" + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "list" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |), + Constant.int 1 + |), + Constant.ellipsis + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "args" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "raw_item" |), + M.get_name (| globals, locals_stack, "raw_rlp" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "args" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "_decode_to" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |), + Constant.int 0 + |); + M.get_name (| globals, locals_stack, "raw_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [ + M.get_name (| globals, locals_stack, "args" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "args" , + make_list [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "t" |); M.get_name (| globals, locals_stack, "raw_item" |) ], + M.call (| + M.get_name (| globals, locals_stack, "zip" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |); + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "args" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "_decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "t" |); + M.get_name (| globals, locals_stack, "raw_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [ + M.get_name (| globals, locals_stack, "args" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "cls" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Bytes0" |); M.get_name (| globals, locals_stack, "Bytes20" |) ] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |), + Constant.int 20 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes20" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "RLPDecodingError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "Bytes has length {}, expected 0 or 20", "format" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "List" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "_name" |), + Constant.str "List" + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "list" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "items" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "raw_item" |), + M.get_name (| globals, locals_stack, "raw_rlp" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "items" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "_decode_to" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |), + Constant.int 0 + |); + M.get_name (| globals, locals_stack, "raw_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "items" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + M.call (| + M.get_name (| globals, locals_stack, "type" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Bytes" |); M.get_subscript (| + M.get_name (| globals, locals_stack, "List" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |) ] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__origin__" |), + M.get_name (| globals, locals_stack, "Union" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |) + ], + make_dict [] + |), + Constant.int 2 + |), + ltac:(M.monadic ( + Compare.not_in (| + M.get_name (| globals, locals_stack, "Bytes" |), + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "RLPDecodingError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "RLP Decoding to type {} is not supported", "format" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "raw_rlp" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |), + Constant.int 0 + |), + M.get_name (| globals, locals_stack, "Bytes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "_decode_to" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |), + Constant.int 1 + |); + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "_decode_to" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "__args__" |), + Constant.int 0 + |); + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "issubclass" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + M.get_name (| globals, locals_stack, "bool" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "raw_rlp" |), + Constant.bytes "01" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + Constant.bool true + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "raw_rlp" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + Constant.bool false + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "TypeError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "Cannot decode {} as {}", "format" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "cls" |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "issubclass" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + M.get_name (| globals, locals_stack, "FixedBytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "cls" |), "LENGTH" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "issubclass" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "raw_rlp" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "issubclass" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |); + make_tuple [ M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "FixedUint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "is_dataclass" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "list" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |); + M.get_name (| globals, locals_stack, "list" |) + ], + make_dict [] + |) |) in + let _ := M.assign_local (| + "args" , + make_list [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "fields" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "field" |); M.get_name (| globals, locals_stack, "rlp_item" |) ], + M.call (| + M.get_name (| globals, locals_stack, "zip" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "fields" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "raw_rlp" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "args" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "_decode_to" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "field" |), "type" |); + M.get_name (| globals, locals_stack, "rlp_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_name (| globals, locals_stack, "T" |); + M.call (| + M.get_name (| globals, locals_stack, "cls" |), + M.get_name (| globals, locals_stack, "args" |), + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "RLPDecodingError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "RLP Decoding to type {} is not supported", "format" |), + make_list [ + M.get_name (| globals, locals_stack, "cls" |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom _decode_to_in_globals : + IsInGlobals globals "_decode_to" (make_function _decode_to). + +Definition decode_to_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "encoded_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_bytes" |) + ], + make_dict [] + |), + Constant.int 1 + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_bytes" |), + Constant.int 0 + |), + Constant.int 128 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "encoded_bytes" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_bytes" |), + Constant.int 0 + |), + Constant.int 183 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "len_raw_data" , + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_bytes" |), + Constant.int 0 + |), + Constant.int 128 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "len_raw_data" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_bytes" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "raw_data" , + M.slice (| + M.get_name (| globals, locals_stack, "encoded_bytes" |), + Constant.int 1, + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "len_raw_data" |) + |), + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "len_raw_data" |), + Constant.int 1 + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "raw_data" |), + Constant.int 0 + |), + Constant.int 128 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "raw_data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "decoded_data_start_idx" , + BinOp.sub (| + BinOp.add (| + Constant.int 1, + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_bytes" |), + Constant.int 0 + |) + |), + Constant.int 183 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "decoded_data_start_idx" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_bytes" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_bytes" |), + Constant.int 1 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "len_decoded_data" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "encoded_bytes" |), + Constant.int 1, + M.get_name (| globals, locals_stack, "decoded_data_start_idx" |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "len_decoded_data" |), + Constant.int 56 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "decoded_data_end_idx" , + BinOp.add (| + M.get_name (| globals, locals_stack, "decoded_data_start_idx" |), + M.get_name (| globals, locals_stack, "len_decoded_data" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "decoded_data_end_idx" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_bytes" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "encoded_bytes" |), + M.get_name (| globals, locals_stack, "decoded_data_start_idx" |), + M.get_name (| globals, locals_stack, "decoded_data_end_idx" |), + Constant.None_ + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom decode_to_bytes_in_globals : + IsInGlobals globals "decode_to_bytes" (make_function decode_to_bytes). + +Definition decode_to_sequence : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "encoded_sequence" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_sequence" |), + Constant.int 0 + |), + Constant.int 247 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "len_joined_encodings" , + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_sequence" |), + Constant.int 0 + |), + Constant.int 192 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "len_joined_encodings" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_sequence" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "joined_encodings" , + M.slice (| + M.get_name (| globals, locals_stack, "encoded_sequence" |), + Constant.int 1, + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "len_joined_encodings" |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "joined_encodings_start_idx" , + BinOp.sub (| + BinOp.add (| + Constant.int 1, + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_sequence" |), + Constant.int 0 + |) + |), + Constant.int 247 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "joined_encodings_start_idx" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_sequence" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_sequence" |), + Constant.int 1 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "len_joined_encodings" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "encoded_sequence" |), + Constant.int 1, + M.get_name (| globals, locals_stack, "joined_encodings_start_idx" |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "len_joined_encodings" |), + Constant.int 56 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "joined_encodings_end_idx" , + BinOp.add (| + M.get_name (| globals, locals_stack, "joined_encodings_start_idx" |), + M.get_name (| globals, locals_stack, "len_joined_encodings" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "joined_encodings_end_idx" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_sequence" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "joined_encodings" , + M.slice (| + M.get_name (| globals, locals_stack, "encoded_sequence" |), + M.get_name (| globals, locals_stack, "joined_encodings_start_idx" |), + M.get_name (| globals, locals_stack, "joined_encodings_end_idx" |), + Constant.None_ + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "decode_joined_encodings" |), + make_list [ + M.get_name (| globals, locals_stack, "joined_encodings" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom decode_to_sequence_in_globals : + IsInGlobals globals "decode_to_sequence" (make_function decode_to_sequence). + +Definition decode_joined_encodings : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "joined_encodings" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "decoded_sequence" , + make_list [] + |) in + let _ := M.assign_local (| + "item_start_idx" , + Constant.int 0 + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "item_start_idx" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "joined_encodings" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_item_length" , + M.call (| + M.get_name (| globals, locals_stack, "decode_item_length" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "joined_encodings" |), + M.get_name (| globals, locals_stack, "item_start_idx" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, locals_stack, "item_start_idx" |), + M.get_name (| globals, locals_stack, "encoded_item_length" |) + |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "joined_encodings" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded_item" , + M.slice (| + M.get_name (| globals, locals_stack, "joined_encodings" |), + M.get_name (| globals, locals_stack, "item_start_idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "item_start_idx" |), + M.get_name (| globals, locals_stack, "encoded_item_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "decoded_sequence" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "decode" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "item_start_idx", + M.get_name (| globals, locals_stack, "encoded_item_length" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "decoded_sequence" |) + |) in + M.pure Constant.None_)). + +Axiom decode_joined_encodings_in_globals : + IsInGlobals globals "decode_joined_encodings" (make_function decode_joined_encodings). + +Definition decode_item_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "encoded_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_data" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "first_rlp_byte" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_data" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "length_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "decoded_data_length" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "first_rlp_byte" |), + Constant.int 128 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "first_rlp_byte" |), + Constant.int 183 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "decoded_data_length" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "first_rlp_byte" |), + Constant.int 128 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "first_rlp_byte" |), + Constant.int 191 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "length_length" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "first_rlp_byte" |), + Constant.int 183 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "length_length" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_data" |), + Constant.int 1 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "decoded_data_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "encoded_data" |), + Constant.int 1, + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "length_length" |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "first_rlp_byte" |), + Constant.int 247 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "decoded_data_length" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "first_rlp_byte" |), + Constant.int 192 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "first_rlp_byte" |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "length_length" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "first_rlp_byte" |), + Constant.int 247 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "length_length" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "encoded_data" |), + Constant.int 1 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "RLPDecodingError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "decoded_data_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "encoded_data" |), + Constant.int 1, + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "length_length" |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + BinOp.add (| + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "length_length" |) + |), + M.get_name (| globals, locals_stack, "decoded_data_length" |) + |) + |) in + M.pure Constant.None_)). + +Axiom decode_item_length_in_globals : + IsInGlobals globals "decode_item_length" (make_function decode_item_length). + +Definition rlp_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom rlp_hash_in_globals : + IsInGlobals globals "rlp_hash" (make_function rlp_hash). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/__init__.md new file mode 100644 index 00000000..d6f1abf6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/__init__.md @@ -0,0 +1,31 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByTimestamp : + IsImported globals "ethereum.fork_criteria" "ByTimestamp". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByTimestamp" |), + make_list [ + Constant.int 1681338455 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/blocks.md new file mode 100644 index 00000000..e00a5309 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/blocks.md @@ -0,0 +1,104 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Bloom : + IsImported globals "ethereum.shanghai.fork_types" "Bloom". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". + +Axiom ethereum_shanghai_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.shanghai.transactions" "LegacyTransaction". + +Definition Withdrawal : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/bloom.md new file mode 100644 index 00000000..5c4243ee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". + +Axiom ethereum_shanghai_fork_types_imports_Bloom : + IsImported globals "ethereum.shanghai.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/fork.md new file mode 100644 index 00000000..5901eda3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/fork.md @@ -0,0 +1,2958 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_imports_vm : + IsImported globals "ethereum.shanghai" "vm". + +Axiom ethereum_shanghai_blocks_imports_Block : + IsImported globals "ethereum.shanghai.blocks" "Block". +Axiom ethereum_shanghai_blocks_imports_Header : + IsImported globals "ethereum.shanghai.blocks" "Header". +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". +Axiom ethereum_shanghai_blocks_imports_Receipt : + IsImported globals "ethereum.shanghai.blocks" "Receipt". +Axiom ethereum_shanghai_blocks_imports_Withdrawal : + IsImported globals "ethereum.shanghai.blocks" "Withdrawal". + +Axiom ethereum_shanghai_bloom_imports_logs_bloom : + IsImported globals "ethereum.shanghai.bloom" "logs_bloom". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Bloom : + IsImported globals "ethereum.shanghai.fork_types" "Bloom". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". + +Axiom ethereum_shanghai_state_imports_State : + IsImported globals "ethereum.shanghai.state" "State". +Axiom ethereum_shanghai_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.shanghai.state" "account_exists_and_is_empty". +Axiom ethereum_shanghai_state_imports_destroy_account : + IsImported globals "ethereum.shanghai.state" "destroy_account". +Axiom ethereum_shanghai_state_imports_get_account : + IsImported globals "ethereum.shanghai.state" "get_account". +Axiom ethereum_shanghai_state_imports_increment_nonce : + IsImported globals "ethereum.shanghai.state" "increment_nonce". +Axiom ethereum_shanghai_state_imports_process_withdrawal : + IsImported globals "ethereum.shanghai.state" "process_withdrawal". +Axiom ethereum_shanghai_state_imports_set_account_balance : + IsImported globals "ethereum.shanghai.state" "set_account_balance". +Axiom ethereum_shanghai_state_imports_state_root : + IsImported globals "ethereum.shanghai.state" "state_root". + +Axiom ethereum_shanghai_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.shanghai.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_shanghai_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.shanghai.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_shanghai_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.shanghai.transactions" "TX_BASE_COST". +Axiom ethereum_shanghai_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.shanghai.transactions" "TX_CREATE_COST". +Axiom ethereum_shanghai_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.shanghai.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_shanghai_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.shanghai.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_shanghai_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.shanghai.transactions" "AccessListTransaction". +Axiom ethereum_shanghai_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.shanghai.transactions" "FeeMarketTransaction". +Axiom ethereum_shanghai_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.shanghai.transactions" "LegacyTransaction". +Axiom ethereum_shanghai_transactions_imports_Transaction : + IsImported globals "ethereum.shanghai.transactions" "Transaction". +Axiom ethereum_shanghai_transactions_imports_decode_transaction : + IsImported globals "ethereum.shanghai.transactions" "decode_transaction". +Axiom ethereum_shanghai_transactions_imports_encode_transaction : + IsImported globals "ethereum.shanghai.transactions" "encode_transaction". + +Axiom ethereum_shanghai_trie_imports_Trie : + IsImported globals "ethereum.shanghai.trie" "Trie". +Axiom ethereum_shanghai_trie_imports_root : + IsImported globals "ethereum.shanghai.trie" "root". +Axiom ethereum_shanghai_trie_imports_trie_set : + IsImported globals "ethereum.shanghai.trie" "trie_set". + +Axiom ethereum_shanghai_utils_message_imports_prepare_message : + IsImported globals "ethereum.shanghai.utils.message" "prepare_message". + +Axiom ethereum_shanghai_vm_gas_imports_init_code_cost : + IsImported globals "ethereum.shanghai.vm.gas" "init_code_cost". + +Axiom ethereum_shanghai_vm_interpreter_imports_MAX_CODE_SIZE : + IsImported globals "ethereum.shanghai.vm.interpreter" "MAX_CODE_SIZE". +Axiom ethereum_shanghai_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.shanghai.vm.interpreter" "process_message_call". + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |), + make_tuple [ ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "prev_randao" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "withdrawals" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "withdrawals_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "withdrawals_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_limit" |); + M.get_name (| globals, locals_stack, "parent_gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_used" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_target" |), + M.get_name (| globals, locals_stack, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "target_fee_gas_delta" |), + M.get_name (| globals, locals_stack, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_base_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_base_fee_per_gas_in_globals : + IsInGlobals globals "calculate_base_fee_per_gas" (make_function calculate_base_fee_per_gas). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |), + Constant.bytes "0000000000000000" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |), + M.get_name (| globals, locals_stack, "EMPTY_OMMER_HASH" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |), + M.get_name (| globals, locals_stack, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "error"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "prev_randao"; "transactions"; "chain_id"; "withdrawals" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "map" |), + make_list [ + M.get_name (| globals, locals_stack, "decode_transaction" |); + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "encode_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "sender_address" |); M.get_name (| globals, locals_stack, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "base_fee_per_gas" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |); M.get_name (| globals, locals_stack, "error" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "error" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "wd" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "withdrawals" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "withdrawals_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "wd" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "process_withdrawal" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "wd" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "wd" |), "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "wd" |), "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "withdrawals_trie" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "address" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_name (| globals, locals_stack, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) + ], + make_dict [] + |), + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "MAX_CODE_SIZE" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + make_tuple [ M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "_address" |); M.get_name (| globals, locals_stack, "keys" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |), + M.get_name (| globals, locals_stack, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_2930_in_globals : + IsInGlobals globals "signing_hash_2930" (make_function signing_hash_2930). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_1559_in_globals : + IsInGlobals globals "signing_hash_1559" (make_function signing_hash_1559). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/fork_types.md new file mode 100644 index 00000000..e9e9fb6c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/state.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/state.md new file mode 100644 index 00000000..3a53b8b5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/state.md @@ -0,0 +1,1385 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_shanghai_blocks_imports_Withdrawal : + IsImported globals "ethereum.shanghai.blocks" "Withdrawal". + +Axiom ethereum_shanghai_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.shanghai.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_shanghai_fork_types_imports_Account : + IsImported globals "ethereum.shanghai.fork_types" "Account". +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". + +Axiom ethereum_shanghai_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.shanghai.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_shanghai_trie_imports_Trie : + IsImported globals "ethereum.shanghai.trie" "Trie". +Axiom ethereum_shanghai_trie_imports_copy_trie : + IsImported globals "ethereum.shanghai.trie" "copy_trie". +Axiom ethereum_shanghai_trie_imports_root : + IsImported globals "ethereum.shanghai.trie" "root". +Axiom ethereum_shanghai_trie_imports_trie_get : + IsImported globals "ethereum.shanghai.trie" "trie_get". +Axiom ethereum_shanghai_trie_imports_trie_set : + IsImported globals "ethereum.shanghai.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom mark_account_created_in_globals : + IsInGlobals globals "mark_account_created" (make_function mark_account_created). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition process_withdrawal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "wd" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increase the balance of the withdrawing account. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "wd" |), "address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom process_withdrawal_in_globals : + IsInGlobals globals "process_withdrawal" (make_function process_withdrawal). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "_" |); M.get_name (| globals, locals_stack, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "original_account_trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "original_value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "original_value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_original_in_globals : + IsInGlobals globals "get_storage_original" (make_function get_storage_original). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/transactions.md new file mode 100644 index 00000000..7fe78fff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/transactions.md @@ -0,0 +1,306 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AccessListTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition FeeMarketTransaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "AccessListTransaction" |); M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_transaction_in_globals : + IsInGlobals globals "encode_transaction" (make_function encode_transaction). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, locals_stack, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, locals_stack, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom decode_transaction_in_globals : + IsInGlobals globals "decode_transaction" (make_function decode_transaction). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/trie.md new file mode 100644 index 00000000..7613b67d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/trie.md @@ -0,0 +1,1654 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_paris_imports_trie : + IsImported globals "ethereum.paris" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_shanghai_blocks_imports_Receipt : + IsImported globals "ethereum.shanghai.blocks" "Receipt". +Axiom ethereum_shanghai_blocks_imports_Withdrawal : + IsImported globals "ethereum.shanghai.blocks" "Withdrawal". + +Axiom ethereum_shanghai_fork_types_imports_Account : + IsImported globals "ethereum.shanghai.fork_types" "Account". +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". +Axiom ethereum_shanghai_fork_types_imports_encode_account : + IsImported globals "ethereum.shanghai.fork_types" "encode_account". + +Axiom ethereum_shanghai_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.shanghai.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); M.get_name (| globals, locals_stack, "Withdrawal" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Withdrawal" |); M.get_name (| globals, locals_stack, "Bytes" |) ] + |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "LegacyTransaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Withdrawal" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/__init__.md new file mode 100644 index 00000000..0c954096 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/address.md new file mode 100644 index 00000000..862514bd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/address.md @@ -0,0 +1,247 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this shanghai version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "salt"; "call_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "salt" |) + |), + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_create2_contract_address_in_globals : + IsInGlobals globals "compute_create2_contract_address" (make_function compute_create2_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/hexadecimal.md new file mode 100644 index 00000000..d8e70d94 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Shanghai types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Bloom : + IsImported globals "ethereum.shanghai.fork_types" "Bloom". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/message.md new file mode 100644 index 00000000..8053e15c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/utils/message.md @@ -0,0 +1,278 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_state_imports_get_account : + IsImported globals "ethereum.shanghai.state" "get_account". + +Axiom ethereum_shanghai_vm_imports_Environment : + IsImported globals "ethereum.shanghai.vm" "Environment". +Axiom ethereum_shanghai_vm_imports_Message : + IsImported globals "ethereum.shanghai.vm" "Message". + +Axiom ethereum_shanghai_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_shanghai_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.shanghai.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, locals_stack, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/__init__.md new file mode 100644 index 00000000..9285c9a9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/__init__.md @@ -0,0 +1,273 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_state_imports_State : + IsImported globals "ethereum.shanghai.state" "State". +Axiom ethereum_shanghai_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.shanghai.state" "account_exists_and_is_empty". + +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/exceptions.md new file mode 100644 index 00000000..2615e180 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/exceptions.md @@ -0,0 +1,181 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Revert : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition WriteInStaticContext : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfBoundsRead : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidParameter : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidContractPrefix : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/gas.md new file mode 100644 index 00000000..201613c6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/gas.md @@ -0,0 +1,981 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition GAS_INIT_CODE_WORD_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). + +Definition init_code_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "init_code_length" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.floor_div (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_INIT_CODE_WORD_COST" |), + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "init_code_length" |) + ], + make_dict [] + |) + |), + Constant.int 32 + |) + |) in + M.pure Constant.None_)). + +Axiom init_code_cost_in_globals : + IsInGlobals globals "init_code_cost" (make_function init_code_cost). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/__init__.md new file mode 100644 index 00000000..b80631d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_shanghai_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.shanghai.vm.instructions" "arithmetic". + +Axiom ethereum_shanghai_vm_instructions_imports_bitwise : + IsImported globals "ethereum.shanghai.vm.instructions" "bitwise". + +Axiom ethereum_shanghai_vm_instructions_imports_block : + IsImported globals "ethereum.shanghai.vm.instructions" "block". + +Axiom ethereum_shanghai_vm_instructions_imports_comparison : + IsImported globals "ethereum.shanghai.vm.instructions" "comparison". + +Axiom ethereum_shanghai_vm_instructions_imports_control_flow : + IsImported globals "ethereum.shanghai.vm.instructions" "control_flow". + +Axiom ethereum_shanghai_vm_instructions_imports_environment : + IsImported globals "ethereum.shanghai.vm.instructions" "environment". + +Axiom ethereum_shanghai_vm_instructions_imports_keccak : + IsImported globals "ethereum.shanghai.vm.instructions" "keccak". + +Axiom ethereum_shanghai_vm_instructions_imports_log : + IsImported globals "ethereum.shanghai.vm.instructions" "log". + +Axiom ethereum_shanghai_vm_instructions_imports_memory : + IsImported globals "ethereum.shanghai.vm.instructions" "memory". + +Axiom ethereum_shanghai_vm_instructions_imports_stack : + IsImported globals "ethereum.shanghai.vm.instructions" "stack". + +Axiom ethereum_shanghai_vm_instructions_imports_storage : + IsImported globals "ethereum.shanghai.vm.instructions" "storage". + +Axiom ethereum_shanghai_vm_instructions_imports_system : + IsImported globals "ethereum.shanghai.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/arithmetic.md new file mode 100644 index 00000000..f72cc7ed --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_shanghai_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_LOW". +Axiom ethereum_shanghai_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_MID". +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/bitwise.md new file mode 100644 index 00000000..ffd8b119 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/bitwise.md @@ -0,0 +1,706 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |), + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shl_in_globals : + IsInGlobals globals "bitwise_shl" (make_function bitwise_shl). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_shr_in_globals : + IsInGlobals globals "bitwise_shr" (make_function bitwise_shr). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "signed_value" |), + M.get_name (| globals, locals_stack, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_sar_in_globals : + IsInGlobals globals "bitwise_sar" (make_function bitwise_sar). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/block.md new file mode 100644 index 00000000..506444ce --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/block.md @@ -0,0 +1,468 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition prev_randao : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "prev_randao" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom prev_randao_in_globals : + IsInGlobals globals "prev_randao" (make_function prev_randao). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom chain_id_in_globals : + IsInGlobals globals "chain_id" (make_function chain_id). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/comparison.md new file mode 100644 index 00000000..c00c42a3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/control_flow.md new file mode 100644 index 00000000..bb61fd2f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_HIGH". +Axiom ethereum_shanghai_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_shanghai_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_MID". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.shanghai.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/environment.md new file mode 100644 index 00000000..6408ea9f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/environment.md @@ -0,0 +1,1610 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.shanghai.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_shanghai_state_imports_get_account : + IsImported globals "ethereum.shanghai.state" "get_account". + +Axiom ethereum_shanghai_utils_address_imports_to_address : + IsImported globals "ethereum.shanghai.utils.address" "to_address". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". +Axiom ethereum_shanghai_vm_memory_imports_memory_write : + IsImported globals "ethereum.shanghai.vm.memory" "memory_write". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_COPY". +Axiom ethereum_shanghai_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_shanghai_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatasize_in_globals : + IsInGlobals globals "returndatasize" (make_function returndatasize). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfBoundsRead" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_name (| globals, locals_stack, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "return_data_start_position" |), + M.get_name (| globals, locals_stack, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom returndatacopy_in_globals : + IsInGlobals globals "returndatacopy" (make_function returndatacopy). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "account" |), + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodehash_in_globals : + IsInGlobals globals "extcodehash" (make_function extcodehash). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom self_balance_in_globals : + IsInGlobals globals "self_balance" (make_function self_balance). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom base_fee_in_globals : + IsInGlobals globals "base_fee" (make_function base_fee). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/keccak.md new file mode 100644 index 00000000..91e40c72 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_KECCAK256". +Axiom ethereum_shanghai_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.shanghai.vm.memory" "memory_read_bytes". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/log.md new file mode 100644 index 00000000..8f4bb801 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/log.md @@ -0,0 +1,269 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.shanghai.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_LOG". +Axiom ethereum_shanghai_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_shanghai_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.shanghai.vm.memory" "memory_read_bytes". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/memory.md new file mode 100644 index 00000000..7073031c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.shanghai.vm.memory" "memory_read_bytes". +Axiom ethereum_shanghai_vm_memory_imports_memory_write : + IsImported globals "ethereum.shanghai.vm.memory" "memory_write". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/stack.md new file mode 100644 index 00000000..1ea0f580 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/stack.md @@ -0,0 +1,1008 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". +Axiom ethereum_shanghai_vm_imports_stack : + IsImported globals "ethereum.shanghai.vm" "stack". + +Axiom ethereum_shanghai_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.shanghai.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "num_bytes" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/storage.md new file mode 100644 index 00000000..b6c0203a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/storage.md @@ -0,0 +1,512 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_state_imports_get_storage : + IsImported globals "ethereum.shanghai.state" "get_storage". +Axiom ethereum_shanghai_state_imports_get_storage_original : + IsImported globals "ethereum.shanghai.state" "get_storage_original". +Axiom ethereum_shanghai_state_imports_set_storage : + IsImported globals "ethereum.shanghai.state" "set_storage". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". +Axiom ethereum_shanghai_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.shanghai.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_shanghai_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_shanghai_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_shanghai_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_shanghai_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "GAS_CALL_STIPEND" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ], + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); M.get_name (| globals, locals_stack, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + M.get_name (| globals, locals_stack, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, locals_stack, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/system.md new file mode 100644 index 00000000..58fb8ed9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/instructions/system.md @@ -0,0 +1,2344 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.shanghai.state" "account_exists_and_is_empty". +Axiom ethereum_shanghai_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.shanghai.state" "account_has_code_or_nonce". +Axiom ethereum_shanghai_state_imports_get_account : + IsImported globals "ethereum.shanghai.state" "get_account". +Axiom ethereum_shanghai_state_imports_increment_nonce : + IsImported globals "ethereum.shanghai.state" "increment_nonce". +Axiom ethereum_shanghai_state_imports_is_account_alive : + IsImported globals "ethereum.shanghai.state" "is_account_alive". +Axiom ethereum_shanghai_state_imports_set_account_balance : + IsImported globals "ethereum.shanghai.state" "set_account_balance". + +Axiom ethereum_shanghai_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.shanghai.utils.address" "compute_contract_address". +Axiom ethereum_shanghai_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.shanghai.utils.address" "compute_create2_contract_address". +Axiom ethereum_shanghai_utils_address_imports_to_address : + IsImported globals "ethereum.shanghai.utils.address" "to_address". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". +Axiom ethereum_shanghai_vm_imports_Message : + IsImported globals "ethereum.shanghai.vm" "Message". +Axiom ethereum_shanghai_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.shanghai.vm" "incorporate_child_on_error". +Axiom ethereum_shanghai_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.shanghai.vm" "incorporate_child_on_success". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". +Axiom ethereum_shanghai_vm_exceptions_imports_Revert : + IsImported globals "ethereum.shanghai.vm.exceptions" "Revert". +Axiom ethereum_shanghai_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.shanghai.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_CREATE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_shanghai_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_shanghai_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_shanghai_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_shanghai_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_ZERO". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_message_call_gas". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". +Axiom ethereum_shanghai_vm_gas_imports_init_code_cost : + IsImported globals "ethereum.shanghai.vm.gas" "init_code_cost". +Axiom ethereum_shanghai_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.shanghai.vm.gas" "max_message_call_gas". + +Axiom ethereum_shanghai_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.shanghai.vm.memory" "memory_read_bytes". +Axiom ethereum_shanghai_vm_memory_imports_memory_write : + IsImported globals "ethereum.shanghai.vm.memory" "memory_write". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size"; "init_code_gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "call_data" |) + ], + make_dict [] + |), + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "MAX_CODE_SIZE" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom generic_create_in_globals : + IsInGlobals globals "generic_create" (make_function generic_create). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "init_code_gas" , + M.call (| + M.get_name (| globals, locals_stack, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |), + M.get_name (| globals, locals_stack, "init_code_gas" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |); + M.get_name (| globals, locals_stack, "init_code_gas" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "init_code_gas" , + M.call (| + M.get_name (| globals, locals_stack, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |), + M.get_name (| globals, locals_stack, "init_code_gas" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "salt" |); + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_create" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "endowment" |); + M.get_name (| globals, locals_stack, "contract_address" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |); + M.get_name (| globals, locals_stack, "init_code_gas" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create2_in_globals : + IsInGlobals globals "create2" (make_function create2). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "value" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "access_gas_cost" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "beneficiary" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "is_static" |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "WriteInStaticContext" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "code_address" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "to" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, locals_stack, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom staticcall_in_globals : + IsInGlobals globals "staticcall" (make_function staticcall). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom revert_in_globals : + IsInGlobals globals "revert" (make_function revert). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/interpreter.md new file mode 100644 index 00000000..786b03b4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/interpreter.md @@ -0,0 +1,697 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.shanghai.state" "account_exists_and_is_empty". +Axiom ethereum_shanghai_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.shanghai.state" "account_has_code_or_nonce". +Axiom ethereum_shanghai_state_imports_begin_transaction : + IsImported globals "ethereum.shanghai.state" "begin_transaction". +Axiom ethereum_shanghai_state_imports_commit_transaction : + IsImported globals "ethereum.shanghai.state" "commit_transaction". +Axiom ethereum_shanghai_state_imports_destroy_storage : + IsImported globals "ethereum.shanghai.state" "destroy_storage". +Axiom ethereum_shanghai_state_imports_increment_nonce : + IsImported globals "ethereum.shanghai.state" "increment_nonce". +Axiom ethereum_shanghai_state_imports_mark_account_created : + IsImported globals "ethereum.shanghai.state" "mark_account_created". +Axiom ethereum_shanghai_state_imports_move_ether : + IsImported globals "ethereum.shanghai.state" "move_ether". +Axiom ethereum_shanghai_state_imports_rollback_transaction : + IsImported globals "ethereum.shanghai.state" "rollback_transaction". +Axiom ethereum_shanghai_state_imports_set_code : + IsImported globals "ethereum.shanghai.state" "set_code". +Axiom ethereum_shanghai_state_imports_touch_account : + IsImported globals "ethereum.shanghai.state" "touch_account". + +Axiom ethereum_shanghai_vm_imports_Message : + IsImported globals "ethereum.shanghai.vm" "Message". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_shanghai_vm_imports_Environment : + IsImported globals "ethereum.shanghai.vm" "Environment". +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.shanghai.vm.exceptions" "AddressCollision". +Axiom ethereum_shanghai_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.shanghai.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_shanghai_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.shanghai.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_shanghai_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.shanghai.vm.exceptions" "InvalidOpcode". +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". +Axiom ethereum_shanghai_vm_exceptions_imports_Revert : + IsImported globals "ethereum.shanghai.vm.exceptions" "Revert". +Axiom ethereum_shanghai_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.shanghai.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_shanghai_vm_instructions_imports_Ops : + IsImported globals "ethereum.shanghai.vm.instructions" "Ops". +Axiom ethereum_shanghai_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.shanghai.vm.instructions" "op_implementation". + +Axiom ethereum_shanghai_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.shanghai.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/memory.md new file mode 100644 index 00000000..a2fa442c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..41a5fb6c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/__init__.md @@ -0,0 +1,124 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_shanghai_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.shanghai.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..5093fd46 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,803 @@ +# ๐Ÿ“ alt_bn128.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.precompiled_contracts.alt_bn128". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |); M.get_name (| globals, locals_stack, "x1_value" |); M.get_name (| globals, locals_stack, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, locals_stack, "p0" |), + M.get_name (| globals, locals_stack, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_add_in_globals : + IsInGlobals globals "alt_bn128_add" (make_function alt_bn128_add). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + make_tuple [ M.get_name (| globals, locals_stack, "x0_value" |); M.get_name (| globals, locals_stack, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Axiom alt_bn128_mul_in_globals : + IsInGlobals globals "alt_bn128_mul" (make_function alt_bn128_mul). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "j" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, locals_stack, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, locals_stack, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_name (| globals, locals_stack, "pairing" |), + make_list [ + M.get_name (| globals, locals_stack, "q" |); + M.get_name (| globals, locals_stack, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom alt_bn128_pairing_check_in_globals : + IsInGlobals globals "alt_bn128_pairing_check" (make_function alt_bn128_pairing_check). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..265463c1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,144 @@ +# ๐Ÿ“ blake2f.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/blake2f.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.precompiled_contracts.blake2f". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.shanghai.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, locals_stack, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "rounds" |); M.get_name (| globals, locals_stack, "h" |); M.get_name (| globals, locals_stack, "m" |); M.get_name (| globals, locals_stack, "t_0" |); M.get_name (| globals, locals_stack, "t_1" |); M.get_name (| globals, locals_stack, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, locals_stack, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidParameter" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, locals_stack, "rounds" |); + M.get_name (| globals, locals_stack, "h" |); + M.get_name (| globals, locals_stack, "m" |); + M.get_name (| globals, locals_stack, "t_0" |); + M.get_name (| globals, locals_stack, "t_1" |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom blake2f_in_globals : + IsInGlobals globals "blake2f" (make_function blake2f). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..35207b96 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..d9b42a9f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_IDENTITY". +Axiom ethereum_shanghai_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..16952c34 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/mapping.md @@ -0,0 +1,80 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_shanghai_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_shanghai_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_shanghai_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_shanghai_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_shanghai_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_shanghai_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_shanghai_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_shanghai_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_shanghai_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..0e8361b1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/modexp.md @@ -0,0 +1,700 @@ +# ๐Ÿ“ modexp.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/modexp.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.precompiled_contracts.modexp". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |); + M.get_name (| globals, locals_stack, "exp_length" |); + M.get_name (| globals, locals_stack, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "exp_start" |); + M.get_name (| globals, locals_stack, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, locals_stack, "exp_start" |), + M.get_name (| globals, locals_stack, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.get_name (| globals, locals_stack, "modulus_start" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exp" |); + M.get_name (| globals, locals_stack, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom modexp_in_globals : + IsInGlobals globals "modexp" (make_function modexp). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Axiom complexity_in_globals : + IsInGlobals globals "complexity" (make_function complexity). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, locals_stack, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, locals_stack, "length_part" |), + M.get_name (| globals, locals_stack, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "count" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom iterations_in_globals : + IsInGlobals globals "iterations" (make_function iterations). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, locals_stack, "complexity" |), + make_list [ + M.get_name (| globals, locals_stack, "base_length" |); + M.get_name (| globals, locals_stack, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, locals_stack, "iterations" |), + make_list [ + M.get_name (| globals, locals_stack, "exponent_length" |); + M.get_name (| globals, locals_stack, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "multiplication_complexity" |), + M.get_name (| globals, locals_stack, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, locals_stack, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom gas_cost_in_globals : + IsInGlobals globals "gas_cost" (make_function gas_cost). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..e441fcbd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_shanghai_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..4a4becb7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_SHA256". +Axiom ethereum_shanghai_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/runtime.md new file mode 100644 index 00000000..94f3dde7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_vm_instructions_imports_Ops : + IsImported globals "ethereum.shanghai.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/stack.md new file mode 100644 index 00000000..d683472f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/shanghai/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/shanghai/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.shanghai.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_shanghai_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.shanghai.vm.exceptions" "StackOverflowError". +Axiom ethereum_shanghai_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.shanghai.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/simulations/base_types.md b/docs/revm-python-spec/revm-verif/spec-coq/simulations/base_types.md new file mode 100644 index 00000000..2e1da1f3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/simulations/base_types.md @@ -0,0 +1,326 @@ +# ๐Ÿ“ base_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/simulations/base_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.CoqOfPython. +Require Import simulations.builtins. + +Import simulations.CoqOfPython.Notations. + +Definition globals : Globals.t := "ethereum.base_types". + +Definition U255_CEIL_VALUE : Z := 2^255. + +Definition U256_CEIL_VALUE : Z := 2^256. + +Module Uint. + Inductive t : Set := + | Make (value : Z). + + Definition get (value : t) : Z := + match value with + | Make value => value + end. + + Definition __add__ (self right_ : t) : t := + Make (get self + get right_). +End Uint. + +Module FixedUint. + Record t : Set := { + MAX_VALUE : Z; + value : Z; + }. + + Definition __add__ (self right_ : t) : M? Exception.t t := + let result := (self.(value) + right_.(value))%Z in + if result >? self.(MAX_VALUE) then + Error.raise (Exception.ArithmeticError ArithmeticError.OverflowError) + else + return? {| + MAX_VALUE := self.(MAX_VALUE); + value := result; + |}. + + Definition wrapping_add (self right_ : t) : t := + let sum := (self.(value) + right_.(value))%Z in + {| + MAX_VALUE := self.(MAX_VALUE); + value := Z.modulo sum self.(MAX_VALUE); + |}. + + Definition __sub__ (self right_ : t) : M? Exception.t t := + let result := (self.(value) - right_.(value))%Z in + if result >? self.(MAX_VALUE) then + Error.raise (Exception.ArithmeticError ArithmeticError.OverflowError) + else + return? {| + MAX_VALUE := self.(MAX_VALUE); + value := result; + |}. + + Definition wrapping_sub (self right_ : t) : t := + let sub := (self.(value) - right_.(value))%Z in + {| + MAX_VALUE := self.(MAX_VALUE); + value := Z.modulo sub self.(MAX_VALUE); + |}. + + Definition __mul__ (self right_ : t) : M? Exception.t t := + let result := (self.(value) * right_.(value))%Z in + if result >? self.(MAX_VALUE) then + Error.raise (Exception.ArithmeticError ArithmeticError.OverflowError) + else + return? {| + MAX_VALUE := self.(MAX_VALUE); + value := result; + |}. + + Definition wrapping_mul (self right_ : t) : t := + let mul := (self.(value) * right_.(value))%Z in + {| + MAX_VALUE := self.(MAX_VALUE); + value := Z.modulo mul self.(MAX_VALUE); + |}. + + Definition bit_and (self right_ : t) : t := + let x := self.(value)%Z in + let y := right_.(value)%Z in + {| + MAX_VALUE := self.(MAX_VALUE); + value := Z.land x y; + |}. + + Definition bit_or (self right_ : t) : t := + let x := self.(value)%Z in + let y := right_.(value)%Z in + {| + MAX_VALUE := self.(MAX_VALUE); + value := Z.lor x y; + |}. + + Definition bit_xor (self right_ : t) : t := + let x := self.(value)%Z in + let y := right_.(value)%Z in + {| + MAX_VALUE := self.(MAX_VALUE); + value := Z.lxor x y; + |}. + + Definition bit_not (self : t) : t := + let x := self.(value)%Z in + {| + MAX_VALUE := self.(MAX_VALUE); + value := Z.lnot x; + |}. +End FixedUint. + +Module U256. + Inductive t : Set := + | Make (value : FixedUint.t). + + Definition of_Z (value : Z) : t := + Make {| + FixedUint.MAX_VALUE := 2^256 - 1; + FixedUint.value := value; + |}. + + Definition get (value : t) : FixedUint.t := + let 'Make value := value in + value. + + Definition to_Z (value : t) : Z := + FixedUint.value (get value). + + Definition to_value (value : t) : Value.t := + Value.Make globals "U256" (Pointer.Imm (Object.wrapper (Data.Integer (to_Z value)))). + + Definition MAX_VALUE : t := U256.of_Z (2^256 - 1). + + Definition __add__ (self right_ : t) : M? Exception.t t := + let? result := FixedUint.__add__ (get self) (get right_) in + return? (Make result). + + Definition wrapping_add (self right_ : t) : t := + Make (FixedUint.wrapping_add (get self) (get right_)). + + Definition __sub__ (self right_ : t) : M? Exception.t t := + let? result := FixedUint.__sub__ (get self) (get right_) in + return? (Make result). + + Definition wrapping_sub (self right_ : t) : t := + Make (FixedUint.wrapping_sub (get self) (get right_)). + + Definition __mul__ (self right_ : t) : M? Exception.t t := + let? result := FixedUint.__mul__ (get self) (get right_) in + return? (Make result). + + Definition wrapping_mul (self right_ : t) : t := + Make (FixedUint.wrapping_mul (get self) (get right_)). + + Definition bit_and (self right_ : t) : t := + Make (FixedUint.bit_and (get self) (get right_)). + + Definition bit_or (self right_ : t) : t := + Make (FixedUint.bit_or (get self) (get right_)). + + Definition bit_xor (self right_ : t) : t := + Make (FixedUint.bit_xor (get self) (get right_)). + + Definition bit_not (self : t) : t := + Make (FixedUint.bit_not (get self)). + (* + def from_signed(cls: Type, value: int) -> "U256": + """ + Creates an unsigned integer representing `value` using two's + complement. + """ + if value >= 0: + return cls(value) + + return cls(value & cls.MAX_VALUE) + *) + (* NOTE: for now we ignore the cls here *) + Definition from_signed (self : t) : t := + let value := U256.to_Z self in + if value >=? 0 + then (U256.of_Z value) + (* TODO: here 2^256 - 1 should be the max value of the corresponded class. + To be modified in the future. *) + else (U256.of_Z (Z.land value (2^256 - 1))). +End U256. + +Module U32. + Inductive t : Set := + | Make (value : FixedUint.t). + + Definition of_Z (value : Z) : t := + Make {| + FixedUint.MAX_VALUE := 2^32 - 1; + FixedUint.value := value; + |}. + + Definition get (value : t) : FixedUint.t := + match value with + | Make value => value + end. +End U32. + +Module U64. + Inductive t : Set := + | Make (value : FixedUint.t). + + Definition of_Z (value : Z) : t := + Make {| + FixedUint.MAX_VALUE := 2^64 - 1; + FixedUint.value := value; + |}. + + Definition get (value : t) : FixedUint.t := + match value with + | Make value => value + end. +End U64. + +Module FixedBytes. + Inductive t : Set := + | Make (bytes : list ascii). + + Definition get (bytes : t) : list ascii := + match bytes with + | Make bytes => bytes + end. +End FixedBytes. + +Module Bytes0. + Inductive t : Set := + | Make (bytes : FixedBytes.t). + + Definition get (bytes : t) : FixedBytes.t := + match bytes with + | Make bytes => bytes + end. +End Bytes0. + +Module Bytes4. + Inductive t : Set := + | Make (bytes : FixedBytes.t). + + Definition get (bytes : t) : FixedBytes.t := + match bytes with + | Make bytes => bytes + end. +End Bytes4. + +Module Bytes8. + Inductive t : Set := + | Make (bytes : FixedBytes.t). + + Definition get (bytes : t) : FixedBytes.t := + match bytes with + | Make bytes => bytes + end. +End Bytes8. + +Module Bytes20. + Inductive t : Set := + | Make (bytes : FixedBytes.t). + + Definition get (bytes : t) : FixedBytes.t := + match bytes with + | Make bytes => bytes + end. +End Bytes20. + +Module Bytes32. + Inductive t : Set := + | Make (bytes : FixedBytes.t). + + Definition get (bytes : t) : FixedBytes.t := + match bytes with + | Make bytes => bytes + end. +End Bytes32. + +Module Bytes48. + Inductive t : Set := + | Make (bytes : FixedBytes.t). + + Definition get (bytes : t) : FixedBytes.t := + match bytes with + | Make bytes => bytes + end. +End Bytes48. + +Module Bytes64. + Inductive t : Set := + | Make (bytes : FixedBytes.t). + + Definition get (bytes : t) : FixedBytes.t := + match bytes with + | Make bytes => bytes + end. +End Bytes64. + +Module Bytes256. + Inductive t : Set := + | Make (bytes : FixedBytes.t). + + Definition get (bytes : t) : FixedBytes.t := + match bytes with + | Make bytes => bytes + end. +End Bytes256. + +Module Bytes. + Inductive t : Set := + | Make (bytes : list ascii). + + Definition get (bytes : t) : list ascii := + match bytes with + | Make bytes => bytes + end. +End Bytes. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/simulations/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/simulations/exceptions.md new file mode 100644 index 00000000..1d35cf31 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/simulations/exceptions.md @@ -0,0 +1,13 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/simulations/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require ethereum.paris.vm.simulations.exceptions. + +Module EthereumException. + Inductive t : Set := + | ExceptionalHalt (exn : exceptions.ExceptionalHalt.t). +End EthereumException. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/simulations/proofs/base_types.md b/docs/revm-python-spec/revm-verif/spec-coq/simulations/proofs/base_types.md new file mode 100644 index 00000000..1c5053fb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/simulations/proofs/base_types.md @@ -0,0 +1,19 @@ +# ๐Ÿ“ base_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/simulations/proofs/base_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Require Import ethereum.simulations.base_types. + +Module Uint. + Definition to_value (value : Uint.t) : Value.t := + Value.Make globals "Uint" (Pointer.Imm (Object.wrapper (Data.Integer (Uint.get value)))). +End Uint. + +Module U256. + Definition to_value (value : U256.t) : Value.t := + Value.Make globals "U256" (Pointer.Imm (Object.wrapper (Data.Integer (U256.to_Z value)))). +End U256. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/simulations/proofs/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/simulations/proofs/exceptions.md new file mode 100644 index 00000000..c82951da --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/simulations/proofs/exceptions.md @@ -0,0 +1,22 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/simulations/proofs/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. +Require Import simulations.proofs.CoqOfPython. +Require Import simulations.proofs.heap. + +Require ethereum.paris.vm.simulations.proofs.exceptions. +Require ethereum.simulations.exceptions. + +Import Run. + +Module EthereumException. + Definition to_value (exn : exceptions.EthereumException.t) : Value.t := + match exn with + | exceptions.EthereumException.ExceptionalHalt exn => + Value.Make "exceptions" "ExceptionalHalt" (Pointer.Imm Object.empty) + end. +End EthereumException. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/__init__.md new file mode 100644 index 00000000..d85df143 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/__init__.md @@ -0,0 +1,33 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 2675000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/blocks.md new file mode 100644 index 00000000..a41f62c0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/blocks.md @@ -0,0 +1,91 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Bloom : + IsImported globals "ethereum.spurious_dragon.fork_types" "Bloom". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". + +Axiom ethereum_spurious_dragon_transactions_imports_Transaction : + IsImported globals "ethereum.spurious_dragon.transactions" "Transaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/bloom.md new file mode 100644 index 00000000..698f77ff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". + +Axiom ethereum_spurious_dragon_fork_types_imports_Bloom : + IsImported globals "ethereum.spurious_dragon.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/fork.md new file mode 100644 index 00000000..0b6f24c3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/fork.md @@ -0,0 +1,2828 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_imports_vm : + IsImported globals "ethereum.spurious_dragon" "vm". + +Axiom ethereum_spurious_dragon_blocks_imports_Block : + IsImported globals "ethereum.spurious_dragon.blocks" "Block". +Axiom ethereum_spurious_dragon_blocks_imports_Header : + IsImported globals "ethereum.spurious_dragon.blocks" "Header". +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". +Axiom ethereum_spurious_dragon_blocks_imports_Receipt : + IsImported globals "ethereum.spurious_dragon.blocks" "Receipt". + +Axiom ethereum_spurious_dragon_bloom_imports_logs_bloom : + IsImported globals "ethereum.spurious_dragon.bloom" "logs_bloom". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Bloom : + IsImported globals "ethereum.spurious_dragon.fork_types" "Bloom". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". + +Axiom ethereum_spurious_dragon_state_imports_State : + IsImported globals "ethereum.spurious_dragon.state" "State". +Axiom ethereum_spurious_dragon_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.spurious_dragon.state" "account_exists_and_is_empty". +Axiom ethereum_spurious_dragon_state_imports_create_ether : + IsImported globals "ethereum.spurious_dragon.state" "create_ether". +Axiom ethereum_spurious_dragon_state_imports_destroy_account : + IsImported globals "ethereum.spurious_dragon.state" "destroy_account". +Axiom ethereum_spurious_dragon_state_imports_get_account : + IsImported globals "ethereum.spurious_dragon.state" "get_account". +Axiom ethereum_spurious_dragon_state_imports_increment_nonce : + IsImported globals "ethereum.spurious_dragon.state" "increment_nonce". +Axiom ethereum_spurious_dragon_state_imports_set_account_balance : + IsImported globals "ethereum.spurious_dragon.state" "set_account_balance". +Axiom ethereum_spurious_dragon_state_imports_state_root : + IsImported globals "ethereum.spurious_dragon.state" "state_root". + +Axiom ethereum_spurious_dragon_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.spurious_dragon.transactions" "TX_BASE_COST". +Axiom ethereum_spurious_dragon_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.spurious_dragon.transactions" "TX_CREATE_COST". +Axiom ethereum_spurious_dragon_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.spurious_dragon.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_spurious_dragon_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.spurious_dragon.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_spurious_dragon_transactions_imports_Transaction : + IsImported globals "ethereum.spurious_dragon.transactions" "Transaction". + +Axiom ethereum_spurious_dragon_trie_imports_Trie : + IsImported globals "ethereum.spurious_dragon.trie" "Trie". +Axiom ethereum_spurious_dragon_trie_imports_root : + IsImported globals "ethereum.spurious_dragon.trie" "root". +Axiom ethereum_spurious_dragon_trie_imports_trie_set : + IsImported globals "ethereum.spurious_dragon.trie" "trie_set". + +Axiom ethereum_spurious_dragon_utils_message_imports_prepare_message : + IsImported globals "ethereum.spurious_dragon.utils.message" "prepare_message". + +Axiom ethereum_spurious_dragon_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.spurious_dragon.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "chain_id" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain_id"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "v" |); M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash_155" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_pre155_in_globals : + IsInGlobals globals "signing_hash_pre155" (make_function signing_hash_pre155). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "chain_id" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); M.get_name (| globals, locals_stack, "chain_id" |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_155_in_globals : + IsInGlobals globals "signing_hash_155" (make_function signing_hash_155). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + Constant.int 1, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 10 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/fork_types.md new file mode 100644 index 00000000..f7200401 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/state.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/state.md new file mode 100644 index 00000000..e5adb2ca --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/state.md @@ -0,0 +1,1215 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_spurious_dragon_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.spurious_dragon.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_spurious_dragon_fork_types_imports_Account : + IsImported globals "ethereum.spurious_dragon.fork_types" "Account". +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". + +Axiom ethereum_spurious_dragon_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.spurious_dragon.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_spurious_dragon_trie_imports_Trie : + IsImported globals "ethereum.spurious_dragon.trie" "Trie". +Axiom ethereum_spurious_dragon_trie_imports_copy_trie : + IsImported globals "ethereum.spurious_dragon.trie" "copy_trie". +Axiom ethereum_spurious_dragon_trie_imports_root : + IsImported globals "ethereum.spurious_dragon.trie" "root". +Axiom ethereum_spurious_dragon_trie_imports_trie_get : + IsImported globals "ethereum.spurious_dragon.trie" "trie_get". +Axiom ethereum_spurious_dragon_trie_imports_trie_set : + IsImported globals "ethereum.spurious_dragon.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom is_account_empty_in_globals : + IsInGlobals globals "is_account_empty" (make_function is_account_empty). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_and_is_empty_in_globals : + IsInGlobals globals "account_exists_and_is_empty" (make_function account_exists_and_is_empty). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom is_account_alive_in_globals : + IsInGlobals globals "is_account_alive" (make_function is_account_alive). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/transactions.md new file mode 100644 index 00000000..15b7ea57 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/transactions.md @@ -0,0 +1,63 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/trie.md new file mode 100644 index 00000000..880c9f12 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/trie.md @@ -0,0 +1,1639 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_tangerine_whistle_imports_trie : + IsImported globals "ethereum.tangerine_whistle" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_spurious_dragon_blocks_imports_Receipt : + IsImported globals "ethereum.spurious_dragon.blocks" "Receipt". + +Axiom ethereum_spurious_dragon_fork_types_imports_Account : + IsImported globals "ethereum.spurious_dragon.fork_types" "Account". +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". +Axiom ethereum_spurious_dragon_fork_types_imports_encode_account : + IsImported globals "ethereum.spurious_dragon.fork_types" "encode_account". + +Axiom ethereum_spurious_dragon_transactions_imports_Transaction : + IsImported globals "ethereum.spurious_dragon.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Receipt" |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/__init__.md new file mode 100644 index 00000000..cda04242 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/address.md new file mode 100644 index 00000000..d248ad40 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/address.md @@ -0,0 +1,160 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this spurious dragon version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/hexadecimal.md new file mode 100644 index 00000000..211add41 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Bloom : + IsImported globals "ethereum.spurious_dragon.fork_types" "Bloom". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/message.md new file mode 100644 index 00000000..f6937278 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/utils/message.md @@ -0,0 +1,221 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_state_imports_get_account : + IsImported globals "ethereum.spurious_dragon.state" "get_account". + +Axiom ethereum_spurious_dragon_vm_imports_Environment : + IsImported globals "ethereum.spurious_dragon.vm" "Environment". +Axiom ethereum_spurious_dragon_vm_imports_Message : + IsImported globals "ethereum.spurious_dragon.vm" "Message". + +Axiom ethereum_spurious_dragon_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.spurious_dragon.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/__init__.md new file mode 100644 index 00000000..cafd352a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/__init__.md @@ -0,0 +1,255 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_state_imports_State : + IsImported globals "ethereum.spurious_dragon.state" "State". +Axiom ethereum_spurious_dragon_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.spurious_dragon.state" "account_exists_and_is_empty". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/exceptions.md new file mode 100644 index 00000000..300d44c1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/exceptions.md @@ -0,0 +1,131 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/gas.md new file mode 100644 index 00000000..fa35ac53 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/gas.md @@ -0,0 +1,928 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/__init__.md new file mode 100644 index 00000000..77d52fc6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "arithmetic". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_bitwise : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "bitwise". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_block : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "block". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_comparison : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "comparison". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_control_flow : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "control_flow". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_environment : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "environment". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_keccak : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "keccak". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_log : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "log". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_memory : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "memory". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_stack : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "stack". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_storage : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "storage". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_system : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/arithmetic.md new file mode 100644 index 00000000..34e5c175 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_MID". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/bitwise.md new file mode 100644 index 00000000..1790e516 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/bitwise.md @@ -0,0 +1,400 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/block.md new file mode 100644 index 00000000..fcedad91 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/block.md @@ -0,0 +1,380 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/comparison.md new file mode 100644 index 00000000..d93d9d4d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/control_flow.md new file mode 100644 index 00000000..c1f7be18 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_HIGH". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_MID". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/environment.md new file mode 100644 index 00000000..708049c4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/environment.md @@ -0,0 +1,1053 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_state_imports_get_account : + IsImported globals "ethereum.spurious_dragon.state" "get_account". + +Axiom ethereum_spurious_dragon_utils_address_imports_to_address : + IsImported globals "ethereum.spurious_dragon.utils.address" "to_address". + +Axiom ethereum_spurious_dragon_vm_memory_imports_buffer_read : + IsImported globals "ethereum.spurious_dragon.vm.memory" "buffer_read". +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_write : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_write". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BALANCE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_COPY". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/keccak.md new file mode 100644 index 00000000..e76fb616 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_KECCAK256". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_read_bytes". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/log.md new file mode 100644 index 00000000..fdf5a853 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/log.md @@ -0,0 +1,254 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_LOG". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_read_bytes". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/memory.md new file mode 100644 index 00000000..e04eefe6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_read_bytes". +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_write : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_write". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/stack.md new file mode 100644 index 00000000..adc927d5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". +Axiom ethereum_spurious_dragon_vm_imports_stack : + IsImported globals "ethereum.spurious_dragon.vm" "stack". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_buffer_read : + IsImported globals "ethereum.spurious_dragon.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/storage.md new file mode 100644 index 00000000..b21db385 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/storage.md @@ -0,0 +1,250 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_spurious_dragon_state_imports_get_storage : + IsImported globals "ethereum.spurious_dragon.state" "get_storage". +Axiom ethereum_spurious_dragon_state_imports_set_storage : + IsImported globals "ethereum.spurious_dragon.state" "set_storage". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SLOAD". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/system.md new file mode 100644 index 00000000..7349408e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/instructions/system.md @@ -0,0 +1,1628 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.spurious_dragon.state" "account_exists_and_is_empty". +Axiom ethereum_spurious_dragon_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.spurious_dragon.state" "account_has_code_or_nonce". +Axiom ethereum_spurious_dragon_state_imports_get_account : + IsImported globals "ethereum.spurious_dragon.state" "get_account". +Axiom ethereum_spurious_dragon_state_imports_increment_nonce : + IsImported globals "ethereum.spurious_dragon.state" "increment_nonce". +Axiom ethereum_spurious_dragon_state_imports_is_account_alive : + IsImported globals "ethereum.spurious_dragon.state" "is_account_alive". +Axiom ethereum_spurious_dragon_state_imports_set_account_balance : + IsImported globals "ethereum.spurious_dragon.state" "set_account_balance". + +Axiom ethereum_spurious_dragon_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.spurious_dragon.utils.address" "compute_contract_address". +Axiom ethereum_spurious_dragon_utils_address_imports_to_address : + IsImported globals "ethereum.spurious_dragon.utils.address" "to_address". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". +Axiom ethereum_spurious_dragon_vm_imports_Message : + IsImported globals "ethereum.spurious_dragon.vm" "Message". +Axiom ethereum_spurious_dragon_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.spurious_dragon.vm" "incorporate_child_on_error". +Axiom ethereum_spurious_dragon_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.spurious_dragon.vm" "incorporate_child_on_success". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_CALL". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_CREATE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_ZERO". +Axiom ethereum_spurious_dragon_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_message_call_gas". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". +Axiom ethereum_spurious_dragon_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "max_message_call_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_read_bytes". +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_write : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_write". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/interpreter.md new file mode 100644 index 00000000..c915e28c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/interpreter.md @@ -0,0 +1,675 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.spurious_dragon.state" "account_exists_and_is_empty". +Axiom ethereum_spurious_dragon_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.spurious_dragon.state" "account_has_code_or_nonce". +Axiom ethereum_spurious_dragon_state_imports_begin_transaction : + IsImported globals "ethereum.spurious_dragon.state" "begin_transaction". +Axiom ethereum_spurious_dragon_state_imports_commit_transaction : + IsImported globals "ethereum.spurious_dragon.state" "commit_transaction". +Axiom ethereum_spurious_dragon_state_imports_destroy_storage : + IsImported globals "ethereum.spurious_dragon.state" "destroy_storage". +Axiom ethereum_spurious_dragon_state_imports_increment_nonce : + IsImported globals "ethereum.spurious_dragon.state" "increment_nonce". +Axiom ethereum_spurious_dragon_state_imports_move_ether : + IsImported globals "ethereum.spurious_dragon.state" "move_ether". +Axiom ethereum_spurious_dragon_state_imports_rollback_transaction : + IsImported globals "ethereum.spurious_dragon.state" "rollback_transaction". +Axiom ethereum_spurious_dragon_state_imports_set_code : + IsImported globals "ethereum.spurious_dragon.state" "set_code". +Axiom ethereum_spurious_dragon_state_imports_touch_account : + IsImported globals "ethereum.spurious_dragon.state" "touch_account". + +Axiom ethereum_spurious_dragon_vm_imports_Message : + IsImported globals "ethereum.spurious_dragon.vm" "Message". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_spurious_dragon_vm_imports_Environment : + IsImported globals "ethereum.spurious_dragon.vm" "Environment". +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "AddressCollision". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "InvalidOpcode". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "OutOfGasError". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_Ops : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "Ops". +Axiom ethereum_spurious_dragon_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "op_implementation". + +Axiom ethereum_spurious_dragon_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.spurious_dragon.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/memory.md new file mode 100644 index 00000000..9df905f8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..187134ed --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/__init__.md @@ -0,0 +1,74 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_spurious_dragon_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.spurious_dragon.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..b306eff9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_buffer_read : + IsImported globals "ethereum.spurious_dragon.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..45729970 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_IDENTITY". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..e3a4419b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/mapping.md @@ -0,0 +1,57 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..dbd002e0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..58c0f4c8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SHA256". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/runtime.md new file mode 100644 index 00000000..ea6f913f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_Ops : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/stack.md new file mode 100644 index 00000000..1ffdefe5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/spurious_dragon/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/spurious_dragon/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.spurious_dragon.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "StackOverflowError". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/__init__.md new file mode 100644 index 00000000..75ae4724 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/__init__.md @@ -0,0 +1,32 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "ByBlockNumber" |), + make_list [ + Constant.int 2463000 + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/blocks.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/blocks.md new file mode 100644 index 00000000..2269a083 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/blocks.md @@ -0,0 +1,91 @@ +# ๐Ÿ“ blocks.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/blocks.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.blocks". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Bloom : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Bloom". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". + +Axiom ethereum_tangerine_whistle_transactions_imports_Transaction : + IsImported globals "ethereum.tangerine_whistle.transactions" "Transaction". + +Definition Header : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Block : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Log : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Receipt : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/bloom.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/bloom.md new file mode 100644 index 00000000..071d2a30 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/bloom.md @@ -0,0 +1,223 @@ +# ๐Ÿ“ bloom.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/bloom.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.bloom". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Bloom : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bloom"; "bloom_entry" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "hash" |), + M.get_name (| globals, locals_stack, "idx" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, locals_stack, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "bloom" |), + M.get_name (| globals, locals_stack, "byte_index" |) + |), + M.get_name (| globals, locals_stack, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom add_to_bloom_in_globals : + IsInGlobals globals "add_to_bloom" (make_function add_to_bloom). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "log" |), + M.get_name (| globals, locals_stack, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "topic" |), + M.get_field (| M.get_name (| globals, locals_stack, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "add_to_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |); + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom logs_bloom_in_globals : + IsInGlobals globals "logs_bloom" (make_function logs_bloom). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/fork.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/fork.md new file mode 100644 index 00000000..5f6ecfbb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/fork.md @@ -0,0 +1,2630 @@ +# ๐Ÿ“ fork.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/fork.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.fork". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_imports_vm : + IsImported globals "ethereum.tangerine_whistle" "vm". + +Axiom ethereum_tangerine_whistle_blocks_imports_Block : + IsImported globals "ethereum.tangerine_whistle.blocks" "Block". +Axiom ethereum_tangerine_whistle_blocks_imports_Header : + IsImported globals "ethereum.tangerine_whistle.blocks" "Header". +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". +Axiom ethereum_tangerine_whistle_blocks_imports_Receipt : + IsImported globals "ethereum.tangerine_whistle.blocks" "Receipt". + +Axiom ethereum_tangerine_whistle_bloom_imports_logs_bloom : + IsImported globals "ethereum.tangerine_whistle.bloom" "logs_bloom". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Bloom : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Bloom". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". + +Axiom ethereum_tangerine_whistle_state_imports_State : + IsImported globals "ethereum.tangerine_whistle.state" "State". +Axiom ethereum_tangerine_whistle_state_imports_create_ether : + IsImported globals "ethereum.tangerine_whistle.state" "create_ether". +Axiom ethereum_tangerine_whistle_state_imports_destroy_account : + IsImported globals "ethereum.tangerine_whistle.state" "destroy_account". +Axiom ethereum_tangerine_whistle_state_imports_get_account : + IsImported globals "ethereum.tangerine_whistle.state" "get_account". +Axiom ethereum_tangerine_whistle_state_imports_increment_nonce : + IsImported globals "ethereum.tangerine_whistle.state" "increment_nonce". +Axiom ethereum_tangerine_whistle_state_imports_set_account_balance : + IsImported globals "ethereum.tangerine_whistle.state" "set_account_balance". +Axiom ethereum_tangerine_whistle_state_imports_state_root : + IsImported globals "ethereum.tangerine_whistle.state" "state_root". + +Axiom ethereum_tangerine_whistle_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.tangerine_whistle.transactions" "TX_BASE_COST". +Axiom ethereum_tangerine_whistle_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.tangerine_whistle.transactions" "TX_CREATE_COST". +Axiom ethereum_tangerine_whistle_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.tangerine_whistle.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_tangerine_whistle_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.tangerine_whistle.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_tangerine_whistle_transactions_imports_Transaction : + IsImported globals "ethereum.tangerine_whistle.transactions" "Transaction". + +Axiom ethereum_tangerine_whistle_trie_imports_Trie : + IsImported globals "ethereum.tangerine_whistle.trie" "Trie". +Axiom ethereum_tangerine_whistle_trie_imports_root : + IsImported globals "ethereum.tangerine_whistle.trie" "root". +Axiom ethereum_tangerine_whistle_trie_imports_trie_set : + IsImported globals "ethereum.tangerine_whistle.trie" "trie_set". + +Axiom ethereum_tangerine_whistle_utils_message_imports_prepare_message : + IsImported globals "ethereum.tangerine_whistle.utils.message" "prepare_message". + +Axiom ethereum_tangerine_whistle_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.tangerine_whistle.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "old" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "old" |) + |) in + M.pure Constant.None_)). + +Axiom apply_fork_in_globals : + IsInGlobals globals "apply_fork" (make_function apply_fork). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, locals_stack, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Axiom get_last_256_block_hashes_in_globals : + IsInGlobals globals "get_last_256_block_hashes" (make_function get_last_256_block_hashes). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "chain"; "block" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |); + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, locals_stack, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "state" |); + M.call (| + M.get_name (| globals, locals_stack, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, locals_stack, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, locals_stack, "block" |), "ommers" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "gas_used" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "transactions_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "state_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "receipt_root" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "block" |), "header" |), "bloom" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom state_transition_in_globals : + IsInGlobals globals "state_transition" (make_function state_transition). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header"; "parent_header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "number" |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |), + M.get_name (| globals, locals_stack, "block_difficulty" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "block_parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom validate_header_in_globals : + IsInGlobals globals "validate_header" (make_function validate_header). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom generate_header_hash_for_pow_in_globals : + IsInGlobals globals "generate_header_hash_for_pow" (make_function generate_header_hash_for_pow). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, locals_stack, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, locals_stack, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "mix_digest" |); M.get_name (| globals, locals_stack, "result" |) ], + M.call (| + M.get_name (| globals, locals_stack, "hashimoto_light" |), + make_list [ + M.get_name (| globals, locals_stack, "header_hash" |); + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "nonce" |); + M.get_name (| globals, locals_stack, "cache" |); + M.call (| + M.get_name (| globals, locals_stack, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "mix_digest" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "mix_digest" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, locals_stack, "header" |), "difficulty" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom validate_proof_of_work_in_globals : + IsInGlobals globals "validate_proof_of_work" (make_function validate_proof_of_work). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "gas_available" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "recover_sender" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "sender_address" |) + |) in + M.pure Constant.None_)). + +Axiom check_transaction_in_globals : + IsInGlobals globals "check_transaction" (make_function check_transaction). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "receipt" |) + |) in + M.pure Constant.None_)). + +Axiom make_receipt_in_globals : + IsInGlobals globals "make_receipt" (make_function make_receipt). + +Definition ApplyBodyOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, locals_stack, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "i" |); M.get_name (| globals, locals_stack, "tx" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, locals_stack, "check_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.get_name (| globals, locals_stack, "gas_available" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "gas_used" |); M.get_name (| globals, locals_stack, "logs" |) ], + M.call (| + M.get_name (| globals, locals_stack, "process_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "env" |); + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, locals_stack, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, locals_stack, "make_receipt" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |); + M.get_name (| globals, locals_stack, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, locals_stack, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "pay_rewards" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "block_number" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_gas_limit" |), + M.get_name (| globals, locals_stack, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, locals_stack, "logs_bloom" |), + make_list [ + M.get_name (| globals, locals_stack, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, locals_stack, "block_gas_used" |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_name (| globals, locals_stack, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, locals_stack, "state_root" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom apply_body_in_globals : + IsInGlobals globals "apply_body" (make_function apply_body). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "ommers"; "block_header"; "chain" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "ommers_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "validate_header" |), + make_list [ + M.get_name (| globals, locals_stack, "ommer" |); + M.get_name (| globals, locals_stack, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "block" |), + M.get_name (| globals, locals_stack, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "ommer_index" |); M.get_name (| globals, locals_stack, "ommer" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "ommers_hashes" |), + M.get_name (| globals, locals_stack, "ommer_index" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "block_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "ommer_hash" |), + M.get_name (| globals, locals_stack, "recent_ommers_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt (| + Constant.int 1, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "ommer_age" |), + M.get_name (| globals, locals_stack, "MAX_OMMER_DEPTH" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_name (| globals, locals_stack, "recent_canonical_block_hashes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, locals_stack, "block_header" |), "parent_hash" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom validate_ommers_in_globals : + IsInGlobals globals "validate_ommers" (make_function validate_ommers). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "block_number"; "coinbase"; "ommers" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "coinbase" |); + M.get_name (| globals, locals_stack, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "ommer" |), + M.get_name (| globals, locals_stack, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_number" |), + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, locals_stack, "ommer_age" |) + |), + M.get_name (| globals, locals_stack, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "create_ether" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "ommer" |), "coinbase" |); + M.get_name (| globals, locals_stack, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Axiom pay_rewards_in_globals : + IsInGlobals globals "pay_rewards" (make_function pay_rewards). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "env"; "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "validate_transaction" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "gas_fee" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "sender_account" |), "balance" |), + M.get_name (| globals, locals_stack, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, locals_stack, "prepare_message" |), + make_list [ + M.get_name (| globals, locals_stack, "sender" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |); + M.get_name (| globals, locals_stack, "gas" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, locals_stack, "process_message_call" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "gas_left" |) + |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_used" |), + M.get_name (| globals, locals_stack, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender" |); + M.get_name (| globals, locals_stack, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, locals_stack, "transaction_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "coinbase" |); + M.get_name (| globals, locals_stack, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, locals_stack, "total_gas_used" |); M.get_field (| M.get_name (| globals, locals_stack, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Axiom process_transaction_in_globals : + IsInGlobals globals "process_transaction" (make_function process_transaction). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, locals_stack, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom validate_transaction_in_globals : + IsInGlobals globals "validate_transaction" (make_function validate_transaction). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "byte" |), + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, locals_stack, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, locals_stack, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "TX_BASE_COST" |), + M.get_name (| globals, locals_stack, "data_cost" |) + |), + M.get_name (| globals, locals_stack, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_intrinsic_cost_in_globals : + IsInGlobals globals "calculate_intrinsic_cost" (make_function calculate_intrinsic_cost). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, locals_stack, "v" |); M.get_name (| globals, locals_stack, "r" |); M.get_name (| globals, locals_stack, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "v" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "r" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "s" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_name (| globals, locals_stack, "s" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, locals_stack, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, locals_stack, "r" |); + M.get_name (| globals, locals_stack, "s" |); + BinOp.sub (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, locals_stack, "signing_hash" |), + make_list [ + M.get_name (| globals, locals_stack, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom recover_sender_in_globals : + IsInGlobals globals "recover_sender" (make_function recover_sender). + +Definition signing_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "tx" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "to" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "value" |); M.get_field (| M.get_name (| globals, locals_stack, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom signing_hash_in_globals : + IsInGlobals globals "signing_hash" (make_function signing_hash). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "header" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_header_hash_in_globals : + IsInGlobals globals "compute_header_hash" (make_function compute_header_hash). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas_limit"; "parent_gas_limit" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, locals_stack, "parent_gas_limit" |), + M.get_name (| globals, locals_stack, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_limit" |), + M.get_name (| globals, locals_stack, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom check_gas_limit_in_globals : + IsInGlobals globals "check_gas_limit" (make_function check_gas_limit). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + BinOp.sub (| + Constant.int 1, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, locals_stack, "block_timestamp" |), + M.get_name (| globals, locals_stack, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 10 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, locals_stack, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "max" |), + make_list [ + M.get_name (| globals, locals_stack, "difficulty" |); + M.get_name (| globals, locals_stack, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_block_difficulty_in_globals : + IsInGlobals globals "calculate_block_difficulty" (make_function calculate_block_difficulty). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/fork_types.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/fork_types.md new file mode 100644 index 00000000..334ab5b9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/fork_types.md @@ -0,0 +1,109 @@ +# ๐Ÿ“ fork_types.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/fork_types.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.fork_types". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, locals_stack, "Bytes256" |) +)). + +Definition Account : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "raw_account_data"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "balance" |); M.get_name (| globals, locals_stack, "storage_root" |); M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom encode_account_in_globals : + IsInGlobals globals "encode_account" (make_function encode_account). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/state.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/state.md new file mode 100644 index 00000000..8dc5e05a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/state.md @@ -0,0 +1,998 @@ +# ๐Ÿ“ state.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/state.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.state". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_tangerine_whistle_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.tangerine_whistle.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_tangerine_whistle_fork_types_imports_Account : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Account". +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". + +Axiom ethereum_tangerine_whistle_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.tangerine_whistle.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_tangerine_whistle_trie_imports_Trie : + IsImported globals "ethereum.tangerine_whistle.trie" "Trie". +Axiom ethereum_tangerine_whistle_trie_imports_copy_trie : + IsImported globals "ethereum.tangerine_whistle.trie" "copy_trie". +Axiom ethereum_tangerine_whistle_trie_imports_root : + IsImported globals "ethereum.tangerine_whistle.trie" "root". +Axiom ethereum_tangerine_whistle_trie_imports_trie_get : + IsImported globals "ethereum.tangerine_whistle.trie" "trie_get". +Axiom ethereum_tangerine_whistle_trie_imports_trie_set : + IsImported globals "ethereum.tangerine_whistle.trie" "trie_set". + +Definition State : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Axiom close_state_in_globals : + IsInGlobals globals "close_state" (make_function close_state). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom begin_transaction_in_globals : + IsInGlobals globals "begin_transaction" (make_function begin_transaction). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom commit_transaction_in_globals : + IsInGlobals globals "commit_transaction" (make_function commit_transaction). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom rollback_transaction_in_globals : + IsInGlobals globals "rollback_transaction" (make_function rollback_transaction). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "account" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_account_in_globals : + IsInGlobals globals "get_account" (make_function get_account). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "account" |) + |) in + M.pure Constant.None_)). + +Axiom get_account_optional_in_globals : + IsInGlobals globals "get_account_optional" (make_function get_account_optional). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "account" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_in_globals : + IsInGlobals globals "set_account" (make_function set_account). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom destroy_account_in_globals : + IsInGlobals globals "destroy_account" (make_function destroy_account). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom destroy_storage_in_globals : + IsInGlobals globals "destroy_storage" (make_function destroy_storage). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom get_storage_in_globals : + IsInGlobals globals "get_storage" (make_function get_storage). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |), + M.get_name (| globals, locals_stack, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "trie_set" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom set_storage_in_globals : + IsInGlobals globals "set_storage" (make_function set_storage). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "address" |), + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_storage_tries" |), + M.get_name (| globals, locals_stack, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom storage_root_in_globals : + IsInGlobals globals "storage_root" (make_function storage_root). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom state_root_in_globals : + IsInGlobals globals "state_root" (make_function state_root). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, locals_stack, "get_account_optional" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom account_exists_in_globals : + IsInGlobals globals "account_exists" (make_function account_exists). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Axiom account_has_code_or_nonce_in_globals : + IsInGlobals globals "account_has_code_or_nonce" (make_function account_has_code_or_nonce). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "f" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.call (| + M.get_name (| globals, locals_stack, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom modify_state_in_globals : + IsInGlobals globals "modify_state" (make_function modify_state). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "sender_address"; "recipient_address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "sender_address" |); + M.get_name (| globals, locals_stack, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "recipient_address" |); + M.get_name (| globals, locals_stack, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom move_ether_in_globals : + IsInGlobals globals "move_ether" (make_function move_ether). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_account_balance_in_globals : + IsInGlobals globals "set_account_balance" (make_function set_account_balance). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom touch_account_in_globals : + IsInGlobals globals "touch_account" (make_function touch_account). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom increment_nonce_in_globals : + IsInGlobals globals "increment_nonce" (make_function increment_nonce). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom set_code_in_globals : + IsInGlobals globals "set_code" (make_function set_code). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "state"; "address"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, locals_stack, "modify_state" |), + make_list [ + M.get_name (| globals, locals_stack, "state" |); + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom create_ether_in_globals : + IsInGlobals globals "create_ether" (make_function create_ether). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/transactions.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/transactions.md new file mode 100644 index 00000000..2a0f12fe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/transactions.md @@ -0,0 +1,63 @@ +# ๐Ÿ“ transactions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/transactions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.transactions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/trie.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/trie.md new file mode 100644 index 00000000..75a1fa2a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/trie.md @@ -0,0 +1,1639 @@ +# ๐Ÿ“ trie.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/trie.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.trie". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_dao_fork_imports_trie : + IsImported globals "ethereum.dao_fork" "trie". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_tangerine_whistle_blocks_imports_Receipt : + IsImported globals "ethereum.tangerine_whistle.blocks" "Receipt". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Account : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Account". +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". +Axiom ethereum_tangerine_whistle_fork_types_imports_encode_account : + IsImported globals "ethereum.tangerine_whistle.fork_types" "encode_account". + +Axiom ethereum_tangerine_whistle_transactions_imports_Transaction : + IsImported globals "ethereum.tangerine_whistle.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Bytes" |); M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |); M.get_name (| globals, locals_stack, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Bytes" |) + |); + M.get_name (| globals, locals_stack, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "Optional" |), + M.get_name (| globals, locals_stack, "Receipt" |) + |); + M.get_name (| globals, locals_stack, "Uint" |); + M.get_name (| globals, locals_stack, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition ExtensionNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition BranchNode : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "LeafNode" |); M.get_name (| globals, locals_stack, "ExtensionNode" |); M.get_name (| globals, locals_stack, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, locals_stack, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_internal_node_in_globals : + IsInGlobals globals "encode_internal_node" (make_function encode_internal_node). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "node"; "storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "encode_account" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + make_tuple [ M.get_name (| globals, locals_stack, "Transaction" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "RLP" |); + M.get_name (| globals, locals_stack, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "node" |); + M.get_name (| globals, locals_stack, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom encode_node_in_globals : + IsInGlobals globals "encode_node" (make_function encode_node). + +Definition Trie : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Subscript *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom copy_trie_in_globals : + IsInGlobals globals "copy_trie" (make_function copy_trie). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom trie_set_in_globals : + IsInGlobals globals "trie_set" (make_function trie_set). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "key" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |); + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom trie_get_in_globals : + IsInGlobals globals "trie_get" (make_function trie_get). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "a"; "b" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "a" |), + M.get_name (| globals, locals_stack, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "b" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom common_prefix_length_in_globals : + IsInGlobals globals "common_prefix_length" (make_function common_prefix_length). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "x"; "is_leaf" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, locals_stack, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "x" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom nibble_list_to_compact_in_globals : + IsInGlobals globals "nibble_list_to_compact" (make_function nibble_list_to_compact). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "bytes_" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "byte_index" |); M.get_name (| globals, locals_stack, "byte" |) ], + M.call (| + M.get_name (| globals, locals_stack, "enumerate" |), + make_list [ + M.get_name (| globals, locals_stack, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom bytes_to_nibble_list_in_globals : + IsInGlobals globals "bytes_to_nibble_list" (make_function bytes_to_nibble_list). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "preimage" |); M.get_name (| globals, locals_stack, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.call (| + M.get_name (| globals, locals_stack, "get_storage_root" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, locals_stack, "encode_node" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "encoded_value" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, locals_stack, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "mapped" |), + M.call (| + M.get_name (| globals, locals_stack, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, locals_stack, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "mapped" |) + |) in + M.pure Constant.None_)). + +Axiom _prepare_trie_in_globals : + IsInGlobals globals "_prepare_trie" (make_function _prepare_trie). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "trie"; "get_storage_root" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, locals_stack, "_prepare_trie" |), + make_list [ + M.get_name (| globals, locals_stack, "trie" |); + M.get_name (| globals, locals_stack, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |); + M.get_name (| globals, locals_stack, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.get_name (| globals, locals_stack, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom root_in_globals : + IsInGlobals globals "root" (make_function root). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "obj"; "level" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, locals_stack, "next" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "iter" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, locals_stack, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix_length" |); + M.call (| + M.get_name (| globals, locals_stack, "common_prefix_length" |), + make_list [ + M.get_name (| globals, locals_stack, "substring" |); + M.slice (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, locals_stack, "arbitrary_key" |), + M.get_name (| globals, locals_stack, "level" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtensionNode" |), + make_list [ + M.get_name (| globals, locals_stack, "prefix" |); + M.call (| + M.get_name (| globals, locals_stack, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "patricialize" |), + make_list [ + M.get_name (| globals, locals_stack, "obj" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "level" |), + M.get_name (| globals, locals_stack, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |); + make_tuple [ M.get_name (| globals, locals_stack, "Account" |); M.get_name (| globals, locals_stack, "Receipt" |); M.get_name (| globals, locals_stack, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "branches" |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "key" |), + M.get_name (| globals, locals_stack, "level" |) + |) + |), + M.get_name (| globals, locals_stack, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, locals_stack, "obj" |), + M.get_name (| globals, locals_stack, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom patricialize_in_globals : + IsInGlobals globals "patricialize" (make_function patricialize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/__init__.md new file mode 100644 index 00000000..a220294f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/address.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/address.md new file mode 100644 index 00000000..6f043791 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/address.md @@ -0,0 +1,160 @@ +# ๐Ÿ“ address.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/utils/address.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.utils.address". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this tangerine whistle version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom to_address_in_globals : + IsInGlobals globals "to_address" (make_function to_address). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "address"; "nonce" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, locals_stack, "address" |); + M.get_name (| globals, locals_stack, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, locals_stack, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.get_name (| globals, locals_stack, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom compute_contract_address_in_globals : + IsInGlobals globals "compute_contract_address" (make_function compute_contract_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/hexadecimal.md new file mode 100644 index 00000000..972b6006 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/hexadecimal.md @@ -0,0 +1,173 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Bloom : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Bloom". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_root_in_globals : + IsInGlobals globals "hex_to_root" (make_function hex_to_root). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bloom_in_globals : + IsInGlobals globals "hex_to_bloom" (make_function hex_to_bloom). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_address_in_globals : + IsInGlobals globals "hex_to_address" (make_function hex_to_address). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/message.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/message.md new file mode 100644 index 00000000..64f7ef0f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/utils/message.md @@ -0,0 +1,221 @@ +# ๐Ÿ“ message.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/utils/message.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.utils.message". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_state_imports_get_account : + IsImported globals "ethereum.tangerine_whistle.state" "get_account". + +Axiom ethereum_tangerine_whistle_vm_imports_Environment : + IsImported globals "ethereum.tangerine_whistle.vm" "Environment". +Axiom ethereum_tangerine_whistle_vm_imports_Message : + IsImported globals "ethereum.tangerine_whistle.vm" "Message". + +Axiom ethereum_tangerine_whistle_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.tangerine_whistle.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_name (| globals, locals_stack, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "isinstance" |), + make_list [ + M.get_name (| globals, locals_stack, "target" |); + M.get_name (| globals, locals_stack, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, locals_stack, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, locals_stack, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_name (| globals, locals_stack, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, locals_stack, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, locals_stack, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom prepare_message_in_globals : + IsInGlobals globals "prepare_message" (make_function prepare_message). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/__init__.md new file mode 100644 index 00000000..6b8bc0d5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/__init__.md @@ -0,0 +1,158 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +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`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_state_imports_State : + IsImported globals "ethereum.tangerine_whistle.state" "State". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Message : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition Evm : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_success_in_globals : + IsInGlobals globals "incorporate_child_on_success" (make_function incorporate_child_on_success). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "child_evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). + +Axiom incorporate_child_on_error_in_globals : + IsInGlobals globals "incorporate_child_on_error" (make_function incorporate_child_on_error). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/exceptions.md new file mode 100644 index 00000000..0203c4bf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/exceptions.md @@ -0,0 +1,131 @@ +# ๐Ÿ“ exceptions.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/exceptions.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.exceptions". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := make_klass {| + Klass.bases := [ + (globals, "EthereumException") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackUnderflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackOverflowError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OutOfGasError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition InvalidOpcode : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ( + "__init__", + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "self"; "code" ] in + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "self" |), "code" |), + M.get_name (| globals, locals_stack, "code" |) + |) in + M.pure Constant.None_)) + ) + ]; +|}. + +Definition InvalidJumpDestError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition StackDepthLimitError : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition AddressCollision : Value.t := make_klass {| + Klass.bases := [ + (globals, "ExceptionalHalt") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/gas.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/gas.md new file mode 100644 index 00000000..d3d48068 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/gas.md @@ -0,0 +1,928 @@ +# ๐Ÿ“ gas.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/gas.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.gas". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition MessageCallGas : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "amount" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.call (| + M.get_name (| globals, locals_stack, "GasAndRefund" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom charge_gas_in_globals : + IsInGlobals globals "charge_gas" (make_function charge_gas). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "size_in_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "size_in_words" |), + M.get_name (| globals, locals_stack, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, locals_stack, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, locals_stack, "linear_cost" |), + M.get_name (| globals, locals_stack, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom calculate_memory_gas_cost_in_globals : + IsInGlobals globals "calculate_memory_gas_cost" (make_function calculate_memory_gas_cost). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "extensions" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.get_name (| globals, locals_stack, "size" |) ], + M.get_name (| globals, locals_stack, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.get_name (| globals, locals_stack, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, locals_stack, "after_size" |), + M.get_name (| globals, locals_stack, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, locals_stack, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, locals_stack, "total_cost" |), + M.get_name (| globals, locals_stack, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, locals_stack, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "ExtendMemory" |), + make_list [ + M.get_name (| globals, locals_stack, "to_be_paid" |); + M.get_name (| globals, locals_stack, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_gas_extend_memory_in_globals : + IsInGlobals globals "calculate_gas_extend_memory" (make_function calculate_gas_extend_memory). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "gas_left" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "extra_gas" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas_left" |), + M.get_name (| globals, locals_stack, "memory_cost" |) + |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, locals_stack, "gas" |), + M.get_name (| globals, locals_stack, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom calculate_message_call_gas_in_globals : + IsInGlobals globals "calculate_message_call_gas" (make_function calculate_message_call_gas). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "gas" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, locals_stack, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Axiom max_message_call_gas_in_globals : + IsInGlobals globals "max_message_call_gas" (make_function max_message_call_gas). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/__init__.md new file mode 100644 index 00000000..7a143183 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/__init__.md @@ -0,0 +1,82 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "arithmetic". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_bitwise : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "bitwise". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_block : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "block". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_comparison : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "comparison". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_control_flow : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "control_flow". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_environment : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "environment". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_keccak : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "keccak". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_log : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "log". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_memory : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "memory". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_stack : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "stack". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_storage : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "storage". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_system : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "system". + +Definition Ops : Value.t := make_klass {| + Klass.bases := [ + (globals, "(* At base: unsupported node type: Attribute *)") + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/arithmetic.md new file mode 100644 index 00000000..5bf2821e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/arithmetic.md @@ -0,0 +1,1272 @@ +# ๐Ÿ“ arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_MID". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom add_in_globals : + IsInGlobals globals "add" (make_function add). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sub_in_globals : + IsInGlobals globals "sub" (make_function sub). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mul_in_globals : + IsInGlobals globals "mul" (make_function mul). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom div_in_globals : + IsInGlobals globals "div" (make_function div). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "dividend" |), + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, locals_stack, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, locals_stack, "dividend" |), + M.get_name (| globals, locals_stack, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sdiv_in_globals : + IsInGlobals globals "sdiv" (make_function sdiv). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mod__in_globals : + IsInGlobals globals "mod" (make_function mod_). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "get_sign" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "abs" |), + make_list [ + M.get_name (| globals, locals_stack, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, locals_stack, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom smod_in_globals : + IsInGlobals globals "smod" (make_function smod). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom addmod_in_globals : + IsInGlobals globals "addmod" (make_function addmod). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |), + M.get_name (| globals, locals_stack, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mulmod_in_globals : + IsInGlobals globals "mulmod" (make_function mulmod). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, locals_stack, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, locals_stack, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pow" |), + make_list [ + M.get_name (| globals, locals_stack, "base" |); + M.get_name (| globals, locals_stack, "exponent" |); + M.get_name (| globals, locals_stack, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom exp_in_globals : + IsInGlobals globals "exp" (make_function exp). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, locals_stack, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.get_name (| globals, locals_stack, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, locals_stack, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, locals_stack, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, locals_stack, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signextend_in_globals : + IsInGlobals globals "signextend" (make_function signextend). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/bitwise.md new file mode 100644 index 00000000..0c6689c0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/bitwise.md @@ -0,0 +1,400 @@ +# ๐Ÿ“ bitwise.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/bitwise.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.bitwise". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_and_in_globals : + IsInGlobals globals "bitwise_and" (make_function bitwise_and). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_or_in_globals : + IsInGlobals globals "bitwise_or" (make_function bitwise_or). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, locals_stack, "x" |), + M.get_name (| globals, locals_stack, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_xor_in_globals : + IsInGlobals globals "bitwise_xor" (make_function bitwise_xor). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, locals_stack, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom bitwise_not_in_globals : + IsInGlobals globals "bitwise_not" (make_function bitwise_not). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, locals_stack, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, locals_stack, "word" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom get_byte_in_globals : + IsInGlobals globals "get_byte" (make_function get_byte). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/block.md new file mode 100644 index 00000000..d4505c82 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/block.md @@ -0,0 +1,380 @@ +# ๐Ÿ“ block.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/block.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.block". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |), + M.get_name (| globals, locals_stack, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom block_hash_in_globals : + IsInGlobals globals "block_hash" (make_function block_hash). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom coinbase_in_globals : + IsInGlobals globals "coinbase" (make_function coinbase). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom timestamp_in_globals : + IsInGlobals globals "timestamp" (make_function timestamp). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom number_in_globals : + IsInGlobals globals "number" (make_function number). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom difficulty_in_globals : + IsInGlobals globals "difficulty" (make_function difficulty). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_limit_in_globals : + IsInGlobals globals "gas_limit" (make_function gas_limit). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/comparison.md new file mode 100644 index 00000000..99cd47dd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/comparison.md @@ -0,0 +1,484 @@ +# ๐Ÿ“ comparison.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/comparison.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.comparison". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom less_than_in_globals : + IsInGlobals globals "less_than" (make_function less_than). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_less_than_in_globals : + IsInGlobals globals "signed_less_than" (make_function signed_less_than). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom greater_than_in_globals : + IsInGlobals globals "greater_than" (make_function greater_than). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom signed_greater_than_in_globals : + IsInGlobals globals "signed_greater_than" (make_function signed_greater_than). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "left" |), + M.get_name (| globals, locals_stack, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom equal_in_globals : + IsInGlobals globals "equal" (make_function equal). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, locals_stack, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom is_zero_in_globals : + IsInGlobals globals "is_zero" (make_function is_zero). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/control_flow.md new file mode 100644 index 00000000..e6f35ea2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/control_flow.md @@ -0,0 +1,382 @@ +# ๐Ÿ“ control_flow.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/control_flow.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.control_flow". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_HIGH". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_MID". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom stop_in_globals : + IsInGlobals globals "stop" (make_function stop). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jump_in_globals : + IsInGlobals globals "jump" (make_function jump). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "jump_dest" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, locals_stack, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom jumpi_in_globals : + IsInGlobals globals "jumpi" (make_function jumpi). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pc_in_globals : + IsInGlobals globals "pc" (make_function pc). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gas_left_in_globals : + IsInGlobals globals "gas_left" (make_function gas_left). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom jumpdest_in_globals : + IsInGlobals globals "jumpdest" (make_function jumpdest). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/environment.md new file mode 100644 index 00000000..b40f9cd2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/environment.md @@ -0,0 +1,1053 @@ +# ๐Ÿ“ environment.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/environment.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.environment". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_state_imports_get_account : + IsImported globals "ethereum.tangerine_whistle.state" "get_account". + +Axiom ethereum_tangerine_whistle_utils_address_imports_to_address : + IsImported globals "ethereum.tangerine_whistle.utils.address" "to_address". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_buffer_read : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "buffer_read". +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_write : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_write". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BALANCE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_COPY". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom address_in_globals : + IsInGlobals globals "address" (make_function address). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom balance_in_globals : + IsInGlobals globals "balance" (make_function balance). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom origin_in_globals : + IsInGlobals globals "origin" (make_function origin). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom caller_in_globals : + IsInGlobals globals "caller" (make_function caller). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callvalue_in_globals : + IsInGlobals globals "callvalue" (make_function callvalue). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "start_index" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldataload_in_globals : + IsInGlobals globals "calldataload" (make_function calldataload). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatasize_in_globals : + IsInGlobals globals "calldatasize" (make_function calldatasize). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |); + M.get_name (| globals, locals_stack, "data_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom calldatacopy_in_globals : + IsInGlobals globals "calldatacopy" (make_function calldatacopy). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codesize_in_globals : + IsInGlobals globals "codesize" (make_function codesize). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom codecopy_in_globals : + IsInGlobals globals "codecopy" (make_function codecopy). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom gasprice_in_globals : + IsInGlobals globals "gasprice" (make_function gasprice). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodesize_in_globals : + IsInGlobals globals "extcodesize" (make_function extcodesize). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_COPY" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_EXTERNAL" |), + M.get_name (| globals, locals_stack, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |); + M.get_name (| globals, locals_stack, "code_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom extcodecopy_in_globals : + IsInGlobals globals "extcodecopy" (make_function extcodecopy). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/keccak.md new file mode 100644 index 00000000..c9e55318 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/keccak.md @@ -0,0 +1,200 @@ +# ๐Ÿ“ keccak.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/keccak.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.keccak". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_KECCAK256". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_read_bytes". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, locals_stack, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_KECCAK256" |), + M.get_name (| globals, locals_stack, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_index" |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom keccak_in_globals : + IsInGlobals globals "keccak" (make_function keccak). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/log.md new file mode 100644 index 00000000..abd28b89 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/log.md @@ -0,0 +1,254 @@ +# ๐Ÿ“ log.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/log.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.log". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_LOG". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_read_bytes". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_topics" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "_" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + M.get_name (| globals, locals_stack, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "topics" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_index" |); M.get_name (| globals, locals_stack, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_DATA" |), + M.get_name (| globals, locals_stack, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_LOG_TOPIC" |), + M.get_name (| globals, locals_stack, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, locals_stack, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, locals_stack, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom log_n_in_globals : + IsInGlobals globals "log_n" (make_function log_n). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "log_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/memory.md new file mode 100644 index 00000000..6a9bc99f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/memory.md @@ -0,0 +1,417 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_read_bytes". +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_write : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_write". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore_in_globals : + IsInGlobals globals "mstore" (make_function mstore). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, locals_stack, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.get_name (| globals, locals_stack, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mstore8_in_globals : + IsInGlobals globals "mstore8" (make_function mstore8). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "start_position" |); M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "start_position" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom mload_in_globals : + IsInGlobals globals "mload" (make_function mload). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom msize_in_globals : + IsInGlobals globals "msize" (make_function msize). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/stack.md new file mode 100644 index 00000000..4500cc0e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/stack.md @@ -0,0 +1,976 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". +Axiom ethereum_tangerine_whistle_vm_imports_stack : + IsImported globals "ethereum.tangerine_whistle.vm" "stack". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_buffer_read : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "num_bytes" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "code" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.get_name (| globals, locals_stack, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, locals_stack, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Axiom push_n_in_globals : + IsInGlobals globals "push_n" (make_function push_n). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom dup_n_in_globals : + IsInGlobals globals "dup_n" (make_function dup_n). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "item_number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, locals_stack, "item_number" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, locals_stack, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom swap_n_in_globals : + IsInGlobals globals "swap_n" (make_function swap_n). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "partial" |), + make_list [ + M.get_name (| globals, locals_stack, "swap_n" |) + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/storage.md new file mode 100644 index 00000000..953fe6d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/storage.md @@ -0,0 +1,250 @@ +# ๐Ÿ“ storage.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/storage.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.storage". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_tangerine_whistle_state_imports_get_storage : + IsImported globals "ethereum.tangerine_whistle.state" "get_storage". +Axiom ethereum_tangerine_whistle_state_imports_set_storage : + IsImported globals "ethereum.tangerine_whistle.state" "set_storage". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SLOAD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sload_in_globals : + IsInGlobals globals "sload" (make_function sload). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, locals_stack, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, locals_stack, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "key" |); + M.get_name (| globals, locals_stack, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom sstore_in_globals : + IsInGlobals globals "sstore" (make_function sstore). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/system.md new file mode 100644 index 00000000..928d4170 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/instructions/system.md @@ -0,0 +1,1582 @@ +# ๐Ÿ“ system.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/system.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.instructions.system". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_state_imports_account_exists : + IsImported globals "ethereum.tangerine_whistle.state" "account_exists". +Axiom ethereum_tangerine_whistle_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.tangerine_whistle.state" "account_has_code_or_nonce". +Axiom ethereum_tangerine_whistle_state_imports_get_account : + IsImported globals "ethereum.tangerine_whistle.state" "get_account". +Axiom ethereum_tangerine_whistle_state_imports_increment_nonce : + IsImported globals "ethereum.tangerine_whistle.state" "increment_nonce". +Axiom ethereum_tangerine_whistle_state_imports_set_account_balance : + IsImported globals "ethereum.tangerine_whistle.state" "set_account_balance". + +Axiom ethereum_tangerine_whistle_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.tangerine_whistle.utils.address" "compute_contract_address". +Axiom ethereum_tangerine_whistle_utils_address_imports_to_address : + IsImported globals "ethereum.tangerine_whistle.utils.address" "to_address". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". +Axiom ethereum_tangerine_whistle_vm_imports_Message : + IsImported globals "ethereum.tangerine_whistle.vm" "Message". +Axiom ethereum_tangerine_whistle_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.tangerine_whistle.vm" "incorporate_child_on_error". +Axiom ethereum_tangerine_whistle_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.tangerine_whistle.vm" "incorporate_child_on_success". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_CALL". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_CREATE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_ZERO". +Axiom ethereum_tangerine_whistle_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_message_call_gas". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". +Axiom ethereum_tangerine_whistle_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "max_message_call_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_read_bytes". +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_write : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_write". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, locals_stack, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, locals_stack, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "balance" |), + M.get_name (| globals, locals_stack, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom create_in_globals : + IsInGlobals globals "create" (make_function create). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_start_position" |); M.get_name (| globals, locals_stack, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_start_position" |); + M.get_name (| globals, locals_stack, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom return__in_globals : + IsInGlobals globals "return_" (make_function return_). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_name (| globals, locals_stack, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, locals_stack, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, locals_stack, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "child_message" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "min" |), + make_list [ + M.get_name (| globals, locals_stack, "memory_output_size" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, locals_stack, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, locals_stack, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Axiom generic_call_in_globals : + IsInGlobals globals "generic_call" (make_function generic_call). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "_account_exists" , + M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "to" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "_account_exists" |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "create_gas_cost" |) + |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "to" |); + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom call_in_globals : + IsInGlobals globals "call" (make_function call). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, locals_stack, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_CALL" |), + M.get_name (| globals, locals_stack, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "sender_balance" |), + M.get_name (| globals, locals_stack, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_name (| globals, locals_stack, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "to" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool true; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom callcode_in_globals : + IsInGlobals globals "callcode" (make_function callcode). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, locals_stack, "account_exists" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, locals_stack, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, locals_stack, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, locals_stack, "originator" |), + M.get_name (| globals, locals_stack, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |), + M.get_name (| globals, locals_stack, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "beneficiary_balance" |), + M.get_name (| globals, locals_stack, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "env" |), "state" |); + M.get_name (| globals, locals_stack, "originator" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "originator" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom selfdestruct_in_globals : + IsInGlobals globals "selfdestruct" (make_function selfdestruct). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, locals_stack, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, locals_stack, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, locals_stack, "memory_input_start_position" |); M.get_name (| globals, locals_stack, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, locals_stack, "memory_output_start_position" |); M.get_name (| globals, locals_stack, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, locals_stack, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, locals_stack, "gas" |); + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |); + M.get_name (| globals, locals_stack, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, locals_stack, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "generic_call" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_field (| M.get_name (| globals, locals_stack, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, locals_stack, "code_address" |); + Constant.bool false; + M.get_name (| globals, locals_stack, "memory_input_start_position" |); + M.get_name (| globals, locals_stack, "memory_input_size" |); + M.get_name (| globals, locals_stack, "memory_output_start_position" |); + M.get_name (| globals, locals_stack, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Axiom delegatecall_in_globals : + IsInGlobals globals "delegatecall" (make_function delegatecall). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/interpreter.md new file mode 100644 index 00000000..a62b88e7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/interpreter.md @@ -0,0 +1,601 @@ +# ๐Ÿ“ interpreter.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/interpreter.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.interpreter". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.tangerine_whistle.state" "account_has_code_or_nonce". +Axiom ethereum_tangerine_whistle_state_imports_begin_transaction : + IsImported globals "ethereum.tangerine_whistle.state" "begin_transaction". +Axiom ethereum_tangerine_whistle_state_imports_commit_transaction : + IsImported globals "ethereum.tangerine_whistle.state" "commit_transaction". +Axiom ethereum_tangerine_whistle_state_imports_destroy_storage : + IsImported globals "ethereum.tangerine_whistle.state" "destroy_storage". +Axiom ethereum_tangerine_whistle_state_imports_move_ether : + IsImported globals "ethereum.tangerine_whistle.state" "move_ether". +Axiom ethereum_tangerine_whistle_state_imports_rollback_transaction : + IsImported globals "ethereum.tangerine_whistle.state" "rollback_transaction". +Axiom ethereum_tangerine_whistle_state_imports_set_code : + IsImported globals "ethereum.tangerine_whistle.state" "set_code". +Axiom ethereum_tangerine_whistle_state_imports_touch_account : + IsImported globals "ethereum.tangerine_whistle.state" "touch_account". + +Axiom ethereum_tangerine_whistle_vm_imports_Message : + IsImported globals "ethereum.tangerine_whistle.vm" "Message". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_tangerine_whistle_vm_imports_Environment : + IsImported globals "ethereum.tangerine_whistle.vm" "Environment". +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "AddressCollision". +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "InvalidOpcode". +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_Ops : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "Ops". +Axiom ethereum_tangerine_whistle_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "op_implementation". + +Axiom ethereum_tangerine_whistle_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.tangerine_whistle.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MessageCallOutput : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "target" |), + M.call (| + M.get_name (| globals, locals_stack, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, locals_stack, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_create_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, locals_stack, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "evm_trace" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom process_message_call_in_globals : + IsInGlobals globals "process_message_call" (make_function process_message_call). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "process_message" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, locals_stack, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_create_message_in_globals : + IsInGlobals globals "process_create_message" (make_function process_create_message). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "depth" |), + M.get_name (| globals, locals_stack, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, locals_stack, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "execute_code" |), + make_list [ + M.get_name (| globals, locals_stack, "message" |); + M.get_name (| globals, locals_stack, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, locals_stack, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, locals_stack, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom process_message_in_globals : + IsInGlobals globals "process_message" (make_function process_message). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "message"; "env" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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 + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, locals_stack, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, locals_stack, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "evm" |) + |) in + M.pure Constant.None_)). + +Axiom execute_code_in_globals : + IsInGlobals globals "execute_code" (make_function execute_code). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/memory.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/memory.md new file mode 100644 index 00000000..eddf43e6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/memory.md @@ -0,0 +1,186 @@ +# ๐Ÿ“ memory.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/memory.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.memory". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_)). + +Axiom memory_write_in_globals : + IsInGlobals globals "memory_write" (make_function memory_write). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "memory"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "memory" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Axiom memory_read_bytes_in_globals : + IsInGlobals globals "memory_read_bytes" (make_function memory_read_bytes). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "buffer"; "start_position"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "buffer" |), + M.get_name (| globals, locals_stack, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, locals_stack, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom buffer_read_in_globals : + IsInGlobals globals "buffer_read" (make_function buffer_read). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..0c8ed55d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/__init__.md @@ -0,0 +1,74 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.precompiled_contracts.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_tangerine_whistle_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.tangerine_whistle.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, locals_stack, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..d7fedc58 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,313 @@ +# ๐Ÿ“ ecrecover.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.precompiled_contracts.ecrecover". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_buffer_read : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + M.get_name (| globals, locals_stack, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.get_name (| globals, locals_stack, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "buffer_read" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, locals_stack, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "r" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, locals_stack, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, locals_stack, "s" |), + M.get_name (| globals, locals_stack, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, locals_stack, "keccak256" |), + make_list [ + M.get_name (| globals, locals_stack, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_address" |) + |) in + M.pure Constant.None_)). + +Axiom ecrecover_in_globals : + IsInGlobals globals "ecrecover" (make_function ecrecover). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..cae10fdc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/identity.md @@ -0,0 +1,106 @@ +# ๐Ÿ“ identity.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.precompiled_contracts.identity". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_IDENTITY". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "data" |) + |) in + M.pure Constant.None_)). + +Axiom identity_in_globals : + IsInGlobals globals "identity" (make_function identity). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..c0354d42 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/mapping.md @@ -0,0 +1,57 @@ +# ๐Ÿ“ mapping.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.precompiled_contracts.mapping". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..a636621f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,137 @@ +# ๐Ÿ“ ripemd160.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.precompiled_contracts.ripemd160". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, locals_stack, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.get_name (| globals, locals_stack, "padded_hash" |) + |) in + M.pure Constant.None_)). + +Axiom ripemd160_in_globals : + IsInGlobals globals "ripemd160" (make_function ripemd160). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..098d4ea5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/precompiled_contracts/sha256.md @@ -0,0 +1,118 @@ +# ๐Ÿ“ sha256.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.precompiled_contracts.sha256". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SHA256". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, locals_stack, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, locals_stack, "charge_gas" |), + make_list [ + M.get_name (| globals, locals_stack, "evm" |); + BinOp.add (| + M.get_name (| globals, locals_stack, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "GAS_SHA256_WORD" |), + M.get_name (| globals, locals_stack, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, locals_stack, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom sha256_in_globals : + IsInGlobals globals "sha256" (make_function sha256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/runtime.md new file mode 100644 index 00000000..4d91f63d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/runtime.md @@ -0,0 +1,169 @@ +# ๐Ÿ“ runtime.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/runtime.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.runtime". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_Ops : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "code" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, locals_stack, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, locals_stack, "pc" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "current_opcode" |), + M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, locals_stack, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, locals_stack, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, locals_stack, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, locals_stack, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). + +Axiom get_valid_jump_destinations_in_globals : + IsInGlobals globals "get_valid_jump_destinations" (make_function get_valid_jump_destinations). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/stack.md b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/stack.md new file mode 100644 index 00000000..ba5a1215 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/tangerine_whistle/vm/stack.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ stack.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/tangerine_whistle/vm/stack.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.tangerine_whistle.vm.stack". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "StackOverflowError". +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom pop_in_globals : + IsInGlobals globals "pop" (make_function pop). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "stack"; "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "stack" |), "append" |), + make_list [ + M.get_name (| globals, locals_stack, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom push_in_globals : + IsInGlobals globals "push" (make_function push). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/trace.md b/docs/revm-python-spec/revm-verif/spec-coq/trace.md new file mode 100644 index 00000000..81069fd4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/trace.md @@ -0,0 +1,139 @@ +# ๐Ÿ“ trace.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/./trace.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.trace". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +.. _trace: + +EVM Trace +^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Defines the functions required for creating evm traces during execution. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Definition TransactionStart : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition TransactionEnd : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition PrecompileStart : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition PrecompileEnd : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OpStart : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OpEnd : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition OpException : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition EvmStop : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition GasAndRefund : Value.t := make_klass {| + Klass.bases := [ + ]; + Klass.class_methods := [ + ]; + Klass.methods := [ + ]; +|}. + +Definition TraceEvent : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, locals_stack, "Union" |), + make_tuple [ M.get_name (| globals, locals_stack, "TransactionStart" |); M.get_name (| globals, locals_stack, "TransactionEnd" |); M.get_name (| globals, locals_stack, "PrecompileStart" |); M.get_name (| globals, locals_stack, "PrecompileEnd" |); M.get_name (| globals, locals_stack, "OpStart" |); M.get_name (| globals, locals_stack, "OpEnd" |); M.get_name (| globals, locals_stack, "OpException" |); M.get_name (| globals, locals_stack, "EvmStop" |); M.get_name (| globals, locals_stack, "GasAndRefund" |) ] + |) +)). + +Definition evm_trace : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "evm"; "event"; "trace_memory"; "trace_stack"; "trace_return_data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Create a trace of the event. + " in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Axiom evm_trace_in_globals : + IsInGlobals globals "evm_trace" (make_function evm_trace). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec-coq/utils/__init__.md new file mode 100644 index 00000000..9e5d7dbc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/utils/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ“ __init__.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/utils/__init__.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.utils.__init__". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility functions used in this specification. +". +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/utils/byte.md b/docs/revm-python-spec/revm-verif/spec-coq/utils/byte.md new file mode 100644 index 00000000..3f107a89 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/utils/byte.md @@ -0,0 +1,97 @@ +# ๐Ÿ“ byte.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/utils/byte.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.utils.byte". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Byte Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Byte specific utility functions used in this specification. +". + +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Definition left_pad_zero_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Left pad zeroes to `value` if it's 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`. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "rjust" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |); + Constant.bytes "00" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom left_pad_zero_bytes_in_globals : + IsInGlobals globals "left_pad_zero_bytes" (make_function left_pad_zero_bytes). + +Definition right_pad_zero_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "size" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Right pad zeroes to `value` if it's 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`. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "value" |), "ljust" |), + make_list [ + M.get_name (| globals, locals_stack, "size" |); + Constant.bytes "00" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom right_pad_zero_bytes_in_globals : + IsInGlobals globals "right_pad_zero_bytes" (make_function right_pad_zero_bytes). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/utils/ensure.md b/docs/revm-python-spec/revm-verif/spec-coq/utils/ensure.md new file mode 100644 index 00000000..d97fbb09 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/utils/ensure.md @@ -0,0 +1,68 @@ +# ๐Ÿ“ ensure.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/utils/ensure.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.utils.ensure". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Ensure (Assertion) Utilities +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Functions that simplify checking assertions and raising exceptions. +". + +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Definition ensure : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value"; "exception" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Does nothing if `value` is truthy, otherwise raises the exception returned + by `exception_class`. + + Parameters + ---------- + + value : + Value that should be true. + + exception : + Constructor for the exception to raise. + " in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, locals_stack, "value" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.raise (| Some (M.get_name (| globals, locals_stack, "exception" |)) |) in + M.pure Constant.None_)). + +Axiom ensure_in_globals : + IsInGlobals globals "ensure" (make_function ensure). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec-coq/utils/hexadecimal.md new file mode 100644 index 00000000..6e0a62ef --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/utils/hexadecimal.md @@ -0,0 +1,546 @@ +# ๐Ÿ“ hexadecimal.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/utils/hexadecimal.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.utils.hexadecimal". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal strings specific utility functions used in this specification. +". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Definition has_hex_prefix : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "hex_string" |), "startswith" |), + make_list [ + Constant.str "0x" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom has_hex_prefix_in_globals : + IsInGlobals globals "has_hex_prefix" (make_function has_hex_prefix). + +Definition remove_hex_prefix : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + Remove 0x prefix from a hex string if present. This function returns the + passed hex string if it isn't prefixed with 0x. + + Parameters + ---------- + hex_string : + The hexadecimal string whose prefix is to be removed. + + Returns + ------- + modified_hex_string : `str` + The hexadecimal string with the 0x prefix removed if present. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, locals_stack, "has_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, locals_stack, "hex_string" |), + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + Constant.str "0x" + ], + make_dict [] + |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "hex_string" |) + |) in + M.pure Constant.None_)). + +Axiom remove_hex_prefix_in_globals : + IsInGlobals globals "remove_hex_prefix" (make_function remove_hex_prefix). + +Definition hex_to_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bytes_in_globals : + IsInGlobals globals "hex_to_bytes" (make_function hex_to_bytes). + +Definition hex_to_bytes8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes8" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 16; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bytes8_in_globals : + IsInGlobals globals "hex_to_bytes8" (make_function hex_to_bytes8). + +Definition hex_to_bytes20 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes20" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 20; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bytes20_in_globals : + IsInGlobals globals "hex_to_bytes20" (make_function hex_to_bytes20). + +Definition hex_to_bytes32 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes32" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 64; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bytes32_in_globals : + IsInGlobals globals "hex_to_bytes32" (make_function hex_to_bytes32). + +Definition hex_to_bytes256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Bytes256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 512; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_bytes256_in_globals : + IsInGlobals globals "hex_to_bytes256" (make_function hex_to_bytes256). + +Definition hex_to_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Hash32" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_hash_in_globals : + IsInGlobals globals "hex_to_hash" (make_function hex_to_hash). + +Definition hex_to_uint : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |); + Constant.int 16 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_uint_in_globals : + IsInGlobals globals "hex_to_uint" (make_function hex_to_uint). + +Definition hex_to_u64 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U64" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |); + Constant.int 16 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_u64_in_globals : + IsInGlobals globals "hex_to_u64" (make_function hex_to_u64). + +Definition hex_to_u256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "hex_string" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + M.call (| + M.get_name (| globals, locals_stack, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, locals_stack, "hex_string" |) + ], + make_dict [] + |); + Constant.int 16 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom hex_to_u256_in_globals : + IsInGlobals globals "hex_to_u256" (make_function hex_to_u256). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/utils/numeric.md b/docs/revm-python-spec/revm-verif/spec-coq/utils/numeric.md new file mode 100644 index 00000000..6f480af9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/utils/numeric.md @@ -0,0 +1,535 @@ +# ๐Ÿ“ numeric.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/utils/numeric.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.utils.numeric". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Numeric Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Numeric operations specific utility functions used in this specification. +". + +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U32 : + IsImported globals "ethereum.base_types" "U32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition get_sign : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.sub (| Constant.int 1 |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + Constant.int 1 + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom get_sign_in_globals : + IsInGlobals globals "get_sign" (make_function get_sign). + +Definition ceil32 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "value" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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`. + " in + let _ := M.assign_local (| + "ceiling" , + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ceiling" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, locals_stack, "remainder" |), + M.call (| + M.get_name (| globals, locals_stack, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, locals_stack, "value" |), + M.get_name (| globals, locals_stack, "ceiling" |) + |), + M.get_name (| globals, locals_stack, "remainder" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Axiom ceil32_in_globals : + IsInGlobals globals "ceil32" (make_function ceil32). + +Definition is_prime : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "number" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, locals_stack, "number" |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "x" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 2; + BinOp.add (| + M.call (| + M.get_name (| globals, locals_stack, "int" |), + make_list [ + BinOp.pow (| + M.get_name (| globals, locals_stack, "number" |), + Constant.float "0.5" + |) + ], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.get_name (| globals, locals_stack, "number" |), + M.get_name (| globals, locals_stack, "x" |) + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Axiom is_prime_in_globals : + IsInGlobals globals "is_prime" (make_function is_prime). + +Definition le_bytes_to_uint32_sequence : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "data" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "sequence" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "i" |), + M.call (| + M.get_name (| globals, locals_stack, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, locals_stack, "len" |), + make_list [ + M.get_name (| globals, locals_stack, "data" |) + ], + make_dict [] + |); + Constant.int 4 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "sequence" |), "append" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "U32" |), "from_le_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, locals_stack, "data" |), + M.get_name (| globals, locals_stack, "i" |), + BinOp.add (| + M.get_name (| globals, locals_stack, "i" |), + Constant.int 4 + |), + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, locals_stack, "tuple" |), + make_list [ + M.get_name (| globals, locals_stack, "sequence" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom le_bytes_to_uint32_sequence_in_globals : + IsInGlobals globals "le_bytes_to_uint32_sequence" (make_function le_bytes_to_uint32_sequence). + +Definition le_uint32_sequence_to_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "sequence" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "result_bytes" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, locals_stack, "item" |), + M.get_name (| globals, locals_stack, "sequence" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "result_bytes", + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "item" |), "to_le_bytes4" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, locals_stack, "result_bytes" |) + |) in + M.pure Constant.None_)). + +Axiom le_uint32_sequence_to_bytes_in_globals : + IsInGlobals globals "le_uint32_sequence_to_bytes" (make_function le_uint32_sequence_to_bytes). + +Definition le_uint32_sequence_to_uint : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "sequence" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "sequence_as_bytes" , + M.call (| + M.get_name (| globals, locals_stack, "le_uint32_sequence_to_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "sequence" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, locals_stack, "Uint" |), "from_le_bytes" |), + make_list [ + M.get_name (| globals, locals_stack, "sequence_as_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Axiom le_uint32_sequence_to_uint_in_globals : + IsInGlobals globals "le_uint32_sequence_to_uint" (make_function le_uint32_sequence_to_uint). + +Definition taylor_exponential : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ "factor"; "numerator"; "denominator" ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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). + + " in + let _ := M.assign_local (| + "i" , + Constant.int 1 + |) in + let _ := M.assign_local (| + "output" , + Constant.int 0 + |) in + let _ := M.assign_local (| + "numerator_accumulated" , + BinOp.mult (| + M.get_name (| globals, locals_stack, "factor" |), + M.get_name (| globals, locals_stack, "denominator" |) + |) + |) in + let _ := + M.while (| + Compare.gt (| + M.get_name (| globals, locals_stack, "numerator_accumulated" |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "output", + M.get_name (| globals, locals_stack, "numerator_accumulated" |) + |) in + let _ := M.assign_local (| + "numerator_accumulated" , + BinOp.floor_div (| + BinOp.mult (| + M.get_name (| globals, locals_stack, "numerator_accumulated" |), + M.get_name (| globals, locals_stack, "numerator" |) + |), + BinOp.mult (| + M.get_name (| globals, locals_stack, "denominator" |), + M.get_name (| globals, locals_stack, "i" |) + |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "i", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + BinOp.floor_div (| + M.get_name (| globals, locals_stack, "output" |), + M.get_name (| globals, locals_stack, "denominator" |) + |) + |) in + M.pure Constant.None_)). + +Axiom taylor_exponential_in_globals : + IsInGlobals globals "taylor_exponential" (make_function taylor_exponential). +``` diff --git a/docs/revm-python-spec/revm-verif/spec-coq/utils/safe_arithmetic.md b/docs/revm-python-spec/revm-verif/spec-coq/utils/safe_arithmetic.md new file mode 100644 index 00000000..2f1f32dd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec-coq/utils/safe_arithmetic.md @@ -0,0 +1,115 @@ +# ๐Ÿ“ safe_arithmetic.v + +[๐Ÿ™ GitHub source](https://github.com/formal-land/coq-of-python/tree/main/CoqOfPython/ethereum/utils/safe_arithmetic.v) + +```coq +Require Import CoqOfPython.CoqOfPython. + +Definition globals : Globals.t := "ethereum.utils.safe_arithmetic". + +Definition locals_stack : list Locals.t := []. + +Definition expr_1 : Value.t := + Constant.str " +Safe Arithmetic for U256 Integer Type +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Safe arithmetic utility functions for U256 integer type. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition u256_safe_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom u256_safe_add_in_globals : + IsInGlobals globals "u256_safe_add" (make_function u256_safe_add). + +Definition u256_safe_multiply : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => + let- locals_stack := M.create_locals locals_stack args kwargs [ ] in + ltac:(M.monadic ( + let _ := Constant.str " + 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. + " in + let _ := M.assign_local (| + "result" , + M.get_subscript (| + M.get_name (| globals, locals_stack, "numbers" |), + Constant.int 0 + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Axiom u256_safe_multiply_in_globals : + IsInGlobals globals "u256_safe_multiply" (make_function u256_safe_multiply). +``` diff --git a/docs/revm-python-spec/revm-verif/spec/__init__.md b/docs/revm-python-spec/revm-verif/spec/__init__.md new file mode 100644 index 00000000..e2a4cf02 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/__init__.md @@ -0,0 +1,33 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/./__init__.py) + +```python +""" +### 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. +""" +import sys + +__version__ = "0.1.0" + +# +# Ensure we can reach 1024 frames of recursion +# +EVM_RECURSION_LIMIT = 1024 * 12 +sys.setrecursionlimit(max(EVM_RECURSION_LIMIT, sys.getrecursionlimit())) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/__init__.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/__init__.md new file mode 100644 index 00000000..0bf3513c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/__init__.md @@ -0,0 +1,14 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/__init__.py) + +```python +""" +The Arrow Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(13773000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/blocks.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/blocks.md new file mode 100644 index 00000000..7ddce119 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/blocks.md @@ -0,0 +1,85 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import LegacyTransaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + base_fee_per_gas: Uint + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Union[Bytes, LegacyTransaction], ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/bloom.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/bloom.md new file mode 100644 index 00000000..5fe0aae9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/fork.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/fork.md new file mode 100644 index 00000000..d6630e72 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/fork.md @@ -0,0 +1,1259 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_ACCESS_LIST_ADDRESS_COST, + TX_ACCESS_LIST_STORAGE_KEY_COST, + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + AccessListTransaction, + FeeMarketTransaction, + LegacyTransaction, + Transaction, + decode_transaction, + encode_transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(2 * 10**18) +BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 +ELASTICITY_MULTIPLIER = 2 +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 +BOMB_DELAY_BLOCKS = 10700000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def calculate_base_fee_per_gas( + block_gas_limit: Uint, + parent_gas_limit: Uint, + parent_gas_used: Uint, + parent_base_fee_per_gas: Uint, +) -> Uint: + """ + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + """ + parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER + + ensure( + check_gas_limit(block_gas_limit, parent_gas_limit), + InvalidBlock, + ) + + if parent_gas_used == parent_gas_target: + expected_base_fee_per_gas = parent_base_fee_per_gas + elif parent_gas_used > parent_gas_target: + gas_used_delta = parent_gas_used - parent_gas_target + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = max( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, + 1, + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas + base_fee_per_gas_delta + ) + else: + gas_used_delta = parent_gas_target - parent_gas_used + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = ( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas - base_fee_per_gas_delta + ) + + return Uint(expected_base_fee_per_gas) + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.gas_used <= header.gas_limit, InvalidBlock) + + 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, + ) + + ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) + + parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + parent_has_ommers, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + header.base_fee_per_gas, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + base_fee_per_gas: Uint, + gas_available: Uint, + chain_id: U64, +) -> Tuple[Address, Uint]: + """ + 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. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + if isinstance(tx, FeeMarketTransaction): + ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock) + ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock) + + priority_fee_per_gas = min( + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas - base_fee_per_gas, + ) + effective_gas_price = priority_fee_per_gas + base_fee_per_gas + else: + ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock) + effective_gas_price = tx.gas_price + + return sender_address, effective_gas_price + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Union[Bytes, Receipt]: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + if isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(receipt) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(receipt) + else: + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + base_fee_per_gas: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Union[LegacyTransaction, Bytes], ...], + ommers: Tuple[Header, ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[ + Bytes, Optional[Union[Bytes, LegacyTransaction]] + ] = Trie(secured=False, default=None) + receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(map(decode_transaction, transactions)): + trie_set( + transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) + ) + + sender_address, effective_gas_price = check_transaction( + tx, base_fee_per_gas, gas_available, chain_id + ) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + base_fee_per_gas=base_fee_per_gas, + gas_price=effective_gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + chain_id=chain_id, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + + if isinstance(tx, FeeMarketTransaction): + max_gas_fee = tx.gas * tx.max_fee_per_gas + else: + max_gas_fee = tx.gas * tx.gas_price + + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + effective_gas_fee = tx.gas * env.gas_price + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + + sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + preaccessed_addresses = set() + preaccessed_storage_keys = set() + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for address, keys in tx.access_list: + preaccessed_addresses.add(address) + for key in keys: + preaccessed_storage_keys.add((address, key)) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + preaccessed_addresses=frozenset(preaccessed_addresses), + preaccessed_storage_keys=frozenset(preaccessed_storage_keys), + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 5, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price + + # For non-1559 transactions env.gas_price == tx.gas_price + priority_fee_per_gas = env.gas_price - env.base_fee_per_gas + transaction_fee = ( + tx.gas - output.gas_left - gas_refund + ) * priority_fee_per_gas + + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + access_list_cost = 0 + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for _address, keys in tx.access_list: + access_list_cost += TX_ACCESS_LIST_ADDRESS_COST + access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + + return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + r, s = tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + ensure( + v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock + ) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_2930(tx) + ) + elif isinstance(tx, FeeMarketTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_1559(tx) + ) + + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def signing_hash_2930(tx: AccessListTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x01" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x02" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, + parent_has_ommers: bool, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max( + (2 if parent_has_ommers else 1) + - int(block_timestamp - parent_timestamp) // 9, + -99, + ) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/fork_types.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/fork_types.md new file mode 100644 index 00000000..9b28cb36 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/state.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/state.md new file mode 100644 index 00000000..57e9b47d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/state.md @@ -0,0 +1,617 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + _created_accounts: Set[Address] = field(default_factory=set) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + del state._created_accounts + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def mark_account_created(state: State, address: Address) -> None: + """ + 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. + """ + state._created_accounts.add(address) + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) + + +def get_storage_original(state: State, address: Address, key: Bytes) -> U256: + """ + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + """ + # In the transaction where an account is created, its preexisting storage + # is ignored. + if address in state._created_accounts: + return U256(0) + + _, original_trie = state._snapshots[0] + original_account_trie = original_trie.get(address) + + if original_account_trie is None: + original_value = U256(0) + else: + original_value = trie_get(original_account_trie, key) + + assert isinstance(original_value, U256) + + return original_value +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/transactions.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/transactions.md new file mode 100644 index 00000000..9d011c49 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/transactions.md @@ -0,0 +1,126 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from .. import rlp +from ..base_types import ( + U64, + U256, + Bytes, + Bytes0, + Bytes32, + Uint, + slotted_freezable, +) +from ..exceptions import InvalidBlock +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 +TX_ACCESS_LIST_ADDRESS_COST = 2400 +TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 + + +@slotted_freezable +@dataclass +class LegacyTransaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class AccessListTransaction: + """ + The transaction type added in EIP-2930 to support access lists. + """ + + chain_id: U64 + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class FeeMarketTransaction: + """ + The transaction type added in EIP-1559. + """ + + chain_id: U64 + nonce: U256 + max_priority_fee_per_gas: Uint + max_fee_per_gas: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +Transaction = Union[ + LegacyTransaction, AccessListTransaction, FeeMarketTransaction +] + + +def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: + """ + Encode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, LegacyTransaction): + return tx + elif isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(tx) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(tx) + else: + raise Exception(f"Unable to encode transaction of type {type(tx)}") + + +def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: + """ + Decode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, Bytes): + if tx[0] == 1: + return rlp.decode_to(AccessListTransaction, tx[1:]) + elif tx[0] == 2: + return rlp.decode_to(FeeMarketTransaction, tx[1:]) + else: + raise InvalidBlock + else: + return tx +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/trie.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/trie.md new file mode 100644 index 00000000..8061b330 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.london import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import LegacyTransaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, LegacyTransaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Union[LegacyTransaction, Bytes]], + Optional[Union[Receipt, Bytes]], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (LegacyTransaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/__init__.md new file mode 100644 index 00000000..304855d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/address.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/address.md new file mode 100644 index 00000000..01b6c591 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/address.md @@ -0,0 +1,97 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this arrow_glacier version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.arrow_glacier.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/hexadecimal.md new file mode 100644 index 00000000..6c38ba5a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/utils/hexadecimal.py) + +```python +""" +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. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/message.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/message.md new file mode 100644 index 00000000..3208b602 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/utils/message.md @@ -0,0 +1,121 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/utils/message.py) + +```python +""" +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. +""" +from typing import FrozenSet, Optional, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Bytes32, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, + preaccessed_addresses: FrozenSet[Address] = frozenset(), + preaccessed_storage_keys: FrozenSet[ + Tuple[(Address, Bytes32)] + ] = frozenset(), +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.arrow_glacier.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + accessed_addresses = set() + accessed_addresses.add(current_target) + accessed_addresses.add(caller) + accessed_addresses.update(PRE_COMPILED_CONTRACTS.keys()) + accessed_addresses.update(preaccessed_addresses) + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + accessed_addresses=accessed_addresses, + accessed_storage_keys=set(preaccessed_storage_keys), + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/__init__.md new file mode 100644 index 00000000..2338b4f5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/__init__.md @@ -0,0 +1,152 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U64, U256, Bytes, Bytes0, Bytes32, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + base_fee_per_gas: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + chain_id: U64 + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: int + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + evm.accessed_addresses.update(child_evm.accessed_addresses) + evm.accessed_storage_keys.update(child_evm.accessed_storage_keys) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/exceptions.md new file mode 100644 index 00000000..7c711307 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/exceptions.md @@ -0,0 +1,138 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class InvalidParameter(ExceptionalHalt): + """ + Raised when invalid parameters are passed. + """ + + pass + + +class InvalidContractPrefix(ExceptionalHalt): + """ + Raised when the new contract code starts with 0xEF. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/gas.md new file mode 100644 index 00000000..896a946f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/gas.md @@ -0,0 +1,245 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(4800) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_FAST_STEP = Uint(5) +GAS_BLAKE2_PER_ROUND = Uint(1) +GAS_COLD_SLOAD = Uint(2100) +GAS_COLD_ACCOUNT_ACCESS = Uint(2600) +GAS_WARM_ACCESS = Uint(100) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/__init__.md new file mode 100644 index 00000000..eebc4e2a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/__init__.md @@ -0,0 +1,360 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + CHAINID = 0x46 + SELFBALANCE = 0x47 + BASEFEE = 0x48 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.CHAINID: block_instructions.chain_id, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SELFBALANCE: environment_instructions.self_balance, + Ops.BASEFEE: environment_instructions.base_fee, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/arithmetic.md new file mode 100644 index 00000000..74013d31 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/bitwise.md new file mode 100644 index 00000000..7624df97 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/block.md new file mode 100644 index 00000000..c5562779 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/block.md @@ -0,0 +1,212 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def chain_id(evm: Evm) -> None: + """ + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.chain_id)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/comparison.md new file mode 100644 index 00000000..86ee0ee5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/control_flow.md new file mode 100644 index 00000000..3aa3b909 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/environment.md new file mode 100644 index 00000000..a5d60dfb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/environment.md @@ -0,0 +1,543 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BASE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_COPY, + GAS_FAST_STEP, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + GAS_WARM_ACCESS, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) + else: + evm.accessed_addresses.add(address) + charge_gas( + evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 + + +def self_balance(evm: Evm) -> None: + """ + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_FAST_STEP) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, evm.message.current_target).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def base_fee(evm: Evm) -> None: + """ + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.base_fee_per_gas)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/keccak.md new file mode 100644 index 00000000..5371a8d5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/log.md new file mode 100644 index 00000000..110c39d2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/memory.md new file mode 100644 index 00000000..e3ab1ac0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/stack.md new file mode 100644 index 00000000..4fc30b7d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/storage.md new file mode 100644 index 00000000..ce695a55 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/storage.md @@ -0,0 +1,132 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.base_types import Uint +from ethereum.utils.ensure import ensure + +from ...state import get_storage, get_storage_original, set_storage +from .. import Evm +from ..exceptions import OutOfGasError, WriteInStaticContext +from ..gas import ( + GAS_CALL_STIPEND, + GAS_COLD_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + GAS_WARM_ACCESS, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + if (evm.message.current_target, key) in evm.accessed_storage_keys: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + charge_gas(evm, GAS_COLD_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + ensure(evm.gas_left > GAS_CALL_STIPEND, OutOfGasError) + + original_value = get_storage_original( + evm.env.state, evm.message.current_target, key + ) + current_value = get_storage(evm.env.state, evm.message.current_target, key) + + gas_cost = Uint(0) + + if (evm.message.current_target, key) not in evm.accessed_storage_keys: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + gas_cost += GAS_COLD_SLOAD + + if original_value == current_value and current_value != new_value: + if original_value == 0: + gas_cost += GAS_STORAGE_SET + else: + gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD + else: + gas_cost += GAS_WARM_ACCESS + + # Refund Counter Calculation + if current_value != new_value: + if original_value != 0 and current_value != 0 and new_value == 0: + # Storage is cleared for the first time in the transaction + evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND) + + if original_value != 0 and current_value == 0: + # Gas refund issued earlier to be reversed + evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND) + + if original_value == new_value: + # Storage slot being restored to its original value + if original_value == 0: + # Slot was originally empty and was SET earlier + evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + else: + # Slot was originally non-empty and was UPDATED earlier + evm.refund_counter += int( + GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS + ) + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/system.md new file mode 100644 index 00000000..e0804d07 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/instructions/system.md @@ -0,0 +1,669 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL_VALUE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_WARM_ACCESS, + GAS_ZERO, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + evm.accessed_addresses.add(contract_address) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + charge_gas( + evm, + GAS_CREATE + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + create_gas_cost = ( + Uint(0) + if is_account_alive(evm.env.state, to) or value == 0 + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if beneficiary not in evm.accessed_addresses: + evm.accessed_addresses.add(beneficiary) + gas_cost += GAS_COLD_ACCOUNT_ACCESS + + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + originator = evm.message.current_target + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/interpreter.md new file mode 100644 index 00000000..7c20d038 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/interpreter.md @@ -0,0 +1,314 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + mark_account_created, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidContractPrefix, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = U256(evm.refund_counter) + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + # In the previously mentioned edge case the preexisting storage is ignored + # for gas refund purposes. In order to do this we must track created + # accounts. + mark_account_created(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + if len(contract_code) > 0: + ensure(contract_code[0] != 0xEF, InvalidContractPrefix) + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=0, + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + accessed_addresses=message.accessed_addresses, + accessed_storage_keys=message.accessed_storage_keys, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/memory.md new file mode 100644 index 00000000..9180f47e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..c31bb52a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/__init__.md @@ -0,0 +1,44 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +BLAKE2F_ADDRESS = hex_to_address("0x09") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..6fb74a8b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(150)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(6000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..dbd3cdad --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,50 @@ +# ๐Ÿ blake2f.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.py) + +```python +""" +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +""" +from ethereum.crypto.blake2 import Blake2b +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import GAS_BLAKE2_PER_ROUND, charge_gas +from ..exceptions import InvalidParameter + + +def blake2f(evm: Evm) -> None: + """ + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + ensure(len(data) == 213, InvalidParameter) + + blake2b = Blake2b() + rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) + + charge_gas(evm, GAS_BLAKE2_PER_ROUND * rounds) + + # OPERATION + ensure(f in [0, 1], InvalidParameter) + + evm.output = blake2b.compress(rounds, h, m, t_0, t_1, f) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..86f0d716 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..1d44e2e5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..adbdff7c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/mapping.md @@ -0,0 +1,52 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + BLAKE2F_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .blake2f import blake2f +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, + BLAKE2F_ADDRESS: blake2f, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..0d4d7f60 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/modexp.md @@ -0,0 +1,174 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = 3 + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = Uint.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + + charge_gas( + evm, + gas_cost(base_length, modulus_length, exp_length, exp_head), + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def complexity(base_length: U256, modulus_length: U256) -> Uint: + """ + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + """ + max_length = max(Uint(base_length), Uint(modulus_length)) + words = (max_length + 7) // 8 + return words**2 + + +def iterations(exponent_length: U256, exponent_head: Uint) -> Uint: + """ + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + """ + if exponent_length <= 32 and exponent_head == 0: + count = Uint(0) + elif exponent_length <= 32: + bit_length = Uint(exponent_head.bit_length()) + + if bit_length > 0: + bit_length -= 1 + + count = bit_length + else: + length_part = 8 * (Uint(exponent_length) - 32) + bits_part = Uint(exponent_head.bit_length()) + + if bits_part > 0: + bits_part -= 1 + + count = length_part + bits_part + + return max(count, Uint(1)) + + +def gas_cost( + base_length: U256, + modulus_length: U256, + exponent_length: U256, + exponent_head: Uint, +) -> Uint: + """ + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + """ + multiplication_complexity = complexity(base_length, modulus_length) + iteration_count = iterations(exponent_length, exponent_head) + cost = multiplication_complexity * iteration_count + cost //= GQUADDIVISOR + return max(Uint(200), cost) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..ceac3ab0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..ecd1e1f9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/runtime.md new file mode 100644 index 00000000..19dc0ca5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/stack.md new file mode 100644 index 00000000..d75268e4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/arrow_glacier/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/arrow_glacier/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/base_types.md b/docs/revm-python-spec/revm-verif/spec/base_types.md new file mode 100644 index 00000000..fcd03d62 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/base_types.md @@ -0,0 +1,990 @@ +# ๐Ÿ base_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/./base_types.py) + +```python +""" +Integer and array types which are used byโ€”but not unique toโ€”Ethereum. + +[`Uint`] represents non-negative integers of arbitrary size, while subclasses +of [`FixedUint`] (like [`U256`] or [`U32`]) represent non-negative integers of +particular sizes. + +Similarly, [`Bytes`] represents arbitrarily long byte sequences, while +subclasses of [`FixedBytes`] (like [`Bytes0`] or [`Bytes64`]) represent +sequences containing an exact number of bytes. + +[`Uint`]: ref:ethereum.base_types.Uint +[`FixedUint`]: ref:ethereum.base_types.FixedUint +[`U32`]: ref:ethereum.base_types.U32 +[`U256`]: ref:ethereum.base_types.U256 +[`Bytes`]: ref:ethereum.base_types.Bytes +[`FixedBytes`]: ref:ethereum.base_types.FixedBytes +[`Bytes0`]: ref:ethereum.base_types.Bytes0 +[`Bytes64`]: ref:ethereum.base_types.Bytes64 +""" + +from dataclasses import is_dataclass, replace +from typing import ( + Any, + Callable, + ClassVar, + Optional, + Protocol, + Tuple, + Type, + TypeVar, + runtime_checkable, +) + + +@runtime_checkable +class SlottedFreezable(Protocol): + """ + A [`Protocol`] implemented by data classes annotated with + [`@slotted_freezable`]. + + [`@slotted_freezable`]: ref:ethereum.base_types.slotted_freezable + [`Protocol`]: https://docs.python.org/library/typing.html#typing.Protocol + """ + + _frozen: bool + + +U255_CEIL_VALUE = 2**255 +""" +Smallest value that requires 256 bits to represent. Mostly used in signed +arithmetic operations, like [`sdiv`]. + +[`sdiv`]: ref:ethereum.frontier.vm.instructions.arithmetic.sdiv +""" + +U256_CEIL_VALUE = 2**256 +""" +Smallest value that requires 257 bits to represent. Used when converting a +[`U256`] in two's complement format to a regular `int` in [`U256.to_signed`]. + +[`U256`]: ref:ethereum.base_types.U256 +[`U256.to_signed`]: ref:ethereum.base_types.U256.to_signed +""" + + +class Uint(int): + """ + Unsigned integer of arbitrary size. + """ + + __slots__ = () + + @classmethod + def from_be_bytes(cls: Type, buffer: "Bytes") -> "Uint": + """ + Converts a sequence of bytes into an arbitrarily sized unsigned integer + from its big endian representation. + """ + return cls(int.from_bytes(buffer, "big")) + + @classmethod + def from_le_bytes(cls: Type, buffer: "Bytes") -> "Uint": + """ + Converts a sequence of bytes into an arbitrarily sized unsigned integer + from its little endian representation. + """ + return cls(int.from_bytes(buffer, "little")) + + def __init__(self, value: int) -> None: + if not isinstance(value, int): + raise TypeError() + + if value < 0: + raise OverflowError() + + def __radd__(self, left: int) -> "Uint": + return self.__add__(left) + + def __add__(self, right: int) -> "Uint": + if not isinstance(right, int): + return NotImplemented + + if right < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__add__(self, right)) + + def __iadd__(self, right: int) -> "Uint": + return self.__add__(right) + + def __sub__(self, right: int) -> "Uint": + if not isinstance(right, int): + return NotImplemented + + if right < 0 or self < right: + raise OverflowError() + + return int.__new__(self.__class__, int.__sub__(self, right)) + + def __rsub__(self, left: int) -> "Uint": + if not isinstance(left, int): + return NotImplemented + + if left < 0 or self > left: + raise OverflowError() + + return int.__new__(self.__class__, int.__rsub__(self, left)) + + def __isub__(self, right: int) -> "Uint": + return self.__sub__(right) + + def __mul__(self, right: int) -> "Uint": + if not isinstance(right, int): + return NotImplemented + + if right < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__mul__(self, right)) + + def __rmul__(self, left: int) -> "Uint": + return self.__mul__(left) + + def __imul__(self, right: int) -> "Uint": + return self.__mul__(right) + + # Explicitly don't override __truediv__, __rtruediv__, and __itruediv__ + # since they return floats anyway. + + def __floordiv__(self, right: int) -> "Uint": + if not isinstance(right, int): + return NotImplemented + + if right < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__floordiv__(self, right)) + + def __rfloordiv__(self, left: int) -> "Uint": + if not isinstance(left, int): + return NotImplemented + + if left < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__rfloordiv__(self, left)) + + def __ifloordiv__(self, right: int) -> "Uint": + return self.__floordiv__(right) + + def __mod__(self, right: int) -> "Uint": + if not isinstance(right, int): + return NotImplemented + + if right < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__mod__(self, right)) + + def __rmod__(self, left: int) -> "Uint": + if not isinstance(left, int): + return NotImplemented + + if left < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__rmod__(self, left)) + + def __imod__(self, right: int) -> "Uint": + return self.__mod__(right) + + def __divmod__(self, right: int) -> Tuple["Uint", "Uint"]: + if not isinstance(right, int): + return NotImplemented + + if right < 0: + raise OverflowError() + + result = int.__divmod__(self, right) + return ( + int.__new__(self.__class__, result[0]), + int.__new__(self.__class__, result[1]), + ) + + def __rdivmod__(self, left: int) -> Tuple["Uint", "Uint"]: + if not isinstance(left, int): + return NotImplemented + + if left < 0: + raise OverflowError() + + result = int.__rdivmod__(self, left) + return ( + int.__new__(self.__class__, result[0]), + int.__new__(self.__class__, result[1]), + ) + + def __pow__( # type: ignore[override] + self, right: int, modulo: Optional[int] = None + ) -> "Uint": + if modulo is not None: + if not isinstance(modulo, int): + return NotImplemented + + if modulo < 0: + raise OverflowError() + + if not isinstance(right, int): + return NotImplemented + + if right < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__pow__(self, right, modulo)) + + def __rpow__( # type: ignore[misc] + self, left: int, modulo: Optional[int] = None + ) -> "Uint": + if modulo is not None: + if not isinstance(modulo, int): + return NotImplemented + + if modulo < 0: + raise OverflowError() + + if not isinstance(left, int): + return NotImplemented + + if left < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__rpow__(self, left, modulo)) + + def __ipow__( # type: ignore[override] + self, right: int, modulo: Optional[int] = None + ) -> "Uint": + return self.__pow__(right, modulo) + + def __xor__(self, right: int) -> "Uint": + if not isinstance(right, int): + return NotImplemented + + if right < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__xor__(self, right)) + + def __rxor__(self, left: int) -> "Uint": + if not isinstance(left, int): + return NotImplemented + + if left < 0: + raise OverflowError() + + return int.__new__(self.__class__, int.__rxor__(self, left)) + + def __ixor__(self, right: int) -> "Uint": + return self.__xor__(right) + + # TODO: Implement and, or, neg, pos, abs, invert, ... + + def to_be_bytes32(self) -> "Bytes32": + """ + Converts this arbitrarily sized unsigned integer into its big endian + representation with exactly 32 bytes. + """ + return Bytes32(self.to_bytes(32, "big")) + + def to_be_bytes(self) -> "Bytes": + """ + Converts this arbitrarily sized unsigned integer into its big endian + representation, without padding. + """ + bit_length = self.bit_length() + byte_length = (bit_length + 7) // 8 + return self.to_bytes(byte_length, "big") + + def to_le_bytes(self, number_bytes: Optional[int] = None) -> "Bytes": + """ + Converts this arbitrarily sized unsigned integer into its little endian + representation, without padding. + """ + if number_bytes is None: + bit_length = self.bit_length() + number_bytes = (bit_length + 7) // 8 + return self.to_bytes(number_bytes, "little") + + +T = TypeVar("T", bound="FixedUint") + + +class FixedUint(int): + """ + Superclass for fixed size unsigned integers. Not intended to be used + directly, but rather to be subclassed. + """ + + MAX_VALUE: ClassVar["FixedUint"] + """ + Largest value that can be represented by this integer type. + """ + + __slots__ = () + + def __init__(self: T, value: int) -> None: + if not isinstance(value, int): + raise TypeError() + + if value < 0 or value > self.MAX_VALUE: + raise OverflowError() + + def __radd__(self: T, left: int) -> T: + return self.__add__(left) + + def __add__(self: T, right: int) -> T: + if not isinstance(right, int): + return NotImplemented + + result = int.__add__(self, right) + + if right < 0 or result > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, result) + + def wrapping_add(self: T, right: int) -> T: + """ + Return a new instance containing `self + right (mod N)`. + + Passing a `right` value greater than [`MAX_VALUE`] or less than zero + will raise a `ValueError`, even if the result would fit in this integer + type. + + [`MAX_VALUE`]: ref:ethereum.base_types.FixedUint.MAX_VALUE + """ + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + # This is a fast way of ensuring that the result is < (2 ** 256) + return int.__new__( + self.__class__, int.__add__(self, right) & self.MAX_VALUE + ) + + def __iadd__(self: T, right: int) -> T: + return self.__add__(right) + + def __sub__(self: T, right: int) -> T: + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE or self < right: + raise OverflowError() + + return int.__new__(self.__class__, int.__sub__(self, right)) + + def wrapping_sub(self: T, right: int) -> T: + """ + Return a new instance containing `self - right (mod N)`. + + Passing a `right` value greater than [`MAX_VALUE`] or less than zero + will raise a `ValueError`, even if the result would fit in this integer + type. + + [`MAX_VALUE`]: ref:ethereum.base_types.FixedUint.MAX_VALUE + """ + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + # This is a fast way of ensuring that the result is < (2 ** 256) + return int.__new__( + self.__class__, int.__sub__(self, right) & self.MAX_VALUE + ) + + def __rsub__(self: T, left: int) -> T: + if not isinstance(left, int): + return NotImplemented + + if left < 0 or left > self.MAX_VALUE or self > left: + raise OverflowError() + + return int.__new__(self.__class__, int.__rsub__(self, left)) + + def __isub__(self: T, right: int) -> T: + return self.__sub__(right) + + def __mul__(self: T, right: int) -> T: + if not isinstance(right, int): + return NotImplemented + + result = int.__mul__(self, right) + + if right < 0 or result > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, result) + + def wrapping_mul(self: T, right: int) -> T: + """ + Return a new instance containing `self * right (mod N)`. + + Passing a `right` value greater than [`MAX_VALUE`] or less than zero + will raise a `ValueError`, even if the result would fit in this integer + type. + + [`MAX_VALUE`]: ref:ethereum.base_types.FixedUint.MAX_VALUE + """ + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + # This is a fast way of ensuring that the result is < (2 ** 256) + return int.__new__( + self.__class__, int.__mul__(self, right) & self.MAX_VALUE + ) + + def __rmul__(self: T, left: int) -> T: + return self.__mul__(left) + + def __imul__(self: T, right: int) -> T: + return self.__mul__(right) + + # Explicitly don't override __truediv__, __rtruediv__, and __itruediv__ + # since they return floats anyway. + + def __floordiv__(self: T, right: int) -> T: + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, int.__floordiv__(self, right)) + + def __rfloordiv__(self: T, left: int) -> T: + if not isinstance(left, int): + return NotImplemented + + if left < 0 or left > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, int.__rfloordiv__(self, left)) + + def __ifloordiv__(self: T, right: int) -> T: + return self.__floordiv__(right) + + def __mod__(self: T, right: int) -> T: + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, int.__mod__(self, right)) + + def __rmod__(self: T, left: int) -> T: + if not isinstance(left, int): + return NotImplemented + + if left < 0 or left > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, int.__rmod__(self, left)) + + def __imod__(self: T, right: int) -> T: + return self.__mod__(right) + + def __divmod__(self: T, right: int) -> Tuple[T, T]: + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + result = super(FixedUint, self).__divmod__(right) + return ( + int.__new__(self.__class__, result[0]), + int.__new__(self.__class__, result[1]), + ) + + def __rdivmod__(self: T, left: int) -> Tuple[T, T]: + if not isinstance(left, int): + return NotImplemented + + if left < 0 or left > self.MAX_VALUE: + raise OverflowError() + + result = super(FixedUint, self).__rdivmod__(left) + return ( + int.__new__(self.__class__, result[0]), + int.__new__(self.__class__, result[1]), + ) + + def __pow__( # type: ignore[override] + self: T, right: int, modulo: Optional[int] = None + ) -> T: + if modulo is not None: + if not isinstance(modulo, int): + return NotImplemented + + if modulo < 0 or modulo > self.MAX_VALUE: + raise OverflowError() + + if not isinstance(right, int): + return NotImplemented + + result = int.__pow__(self, right, modulo) + + if right < 0 or right > self.MAX_VALUE or result > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, result) + + def wrapping_pow(self: T, right: int, modulo: Optional[int] = None) -> T: + """ + Return a new instance containing `self ** right (mod modulo)`. + + If omitted, `modulo` defaults to `Uint(self.MAX_VALUE) + 1`. + + Passing a `right` or `modulo` value greater than [`MAX_VALUE`] or + less than zero will raise a `ValueError`, even if the result would fit + in this integer type. + + [`MAX_VALUE`]: ref:ethereum.base_types.FixedUint.MAX_VALUE + """ + if modulo is not None: + if not isinstance(modulo, int): + return NotImplemented + + if modulo < 0 or modulo > self.MAX_VALUE: + raise OverflowError() + + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + # This is a fast way of ensuring that the result is < (2 ** 256) + return int.__new__( + self.__class__, int.__pow__(self, right, modulo) & self.MAX_VALUE + ) + + def __rpow__( # type: ignore[misc] + self: T, left: int, modulo: Optional[int] = None + ) -> T: + if modulo is not None: + if not isinstance(modulo, int): + return NotImplemented + + if modulo < 0 or modulo > self.MAX_VALUE: + raise OverflowError() + + if not isinstance(left, int): + return NotImplemented + + if left < 0 or left > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, int.__rpow__(self, left, modulo)) + + def __ipow__( # type: ignore[override] + self: T, right: int, modulo: Optional[int] = None + ) -> T: + return self.__pow__(right, modulo) + + def __and__(self: T, right: int) -> T: + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, int.__and__(self, right)) + + def __or__(self: T, right: int) -> T: + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, int.__or__(self, right)) + + def __xor__(self: T, right: int) -> T: + if not isinstance(right, int): + return NotImplemented + + if right < 0 or right > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, int.__xor__(self, right)) + + def __rxor__(self: T, left: int) -> T: + if not isinstance(left, int): + return NotImplemented + + if left < 0 or left > self.MAX_VALUE: + raise OverflowError() + + return int.__new__(self.__class__, int.__rxor__(self, left)) + + def __ixor__(self: T, right: int) -> T: + return self.__xor__(right) + + def __invert__(self: T) -> T: + return int.__new__( + self.__class__, int.__invert__(self) & self.MAX_VALUE + ) + + def __rshift__(self: T, shift_by: int) -> T: + if not isinstance(shift_by, int): + return NotImplemented + return int.__new__(self.__class__, int.__rshift__(self, shift_by)) + + def to_be_bytes(self) -> "Bytes": + """ + Converts this unsigned integer into its big endian representation, + omitting leading zero bytes. + """ + bit_length = self.bit_length() + byte_length = (bit_length + 7) // 8 + return self.to_bytes(byte_length, "big") + + # TODO: Implement neg, pos, abs ... + + +class U256(FixedUint): + """ + Unsigned integer, which can represent `0` to `2 ** 256 - 1`, inclusive. + """ + + MAX_VALUE: ClassVar["U256"] + """ + Largest value that can be represented by this integer type. + """ + + __slots__ = () + + @classmethod + def from_be_bytes(cls: Type, buffer: "Bytes") -> "U256": + """ + Converts a sequence of bytes into a fixed sized unsigned integer + from its big endian representation. + """ + if len(buffer) > 32: + raise ValueError() + + return cls(int.from_bytes(buffer, "big")) + + @classmethod + def from_signed(cls: Type, value: int) -> "U256": + """ + Creates an unsigned integer representing `value` using two's + complement. + """ + if value >= 0: + return cls(value) + + return cls(value & cls.MAX_VALUE) + + def to_be_bytes32(self) -> "Bytes32": + """ + Converts this 256-bit unsigned integer into its big endian + representation with exactly 32 bytes. + """ + return Bytes32(self.to_bytes(32, "big")) + + def to_signed(self) -> int: + """ + Decodes a signed integer from its two's complement representation. + """ + if self.bit_length() < 256: + # This means that the sign bit is 0 + return int(self) + + # -1 * (2's complement of U256 value) + return int(self) - U256_CEIL_VALUE + + +U256.MAX_VALUE = int.__new__(U256, (2**256) - 1) + + +class U32(FixedUint): + """ + Unsigned positive integer, which can represent `0` to `2 ** 32 - 1`, + inclusive. + """ + + MAX_VALUE: ClassVar["U32"] + """ + Largest value that can be represented by this integer type. + """ + + __slots__ = () + + @classmethod + def from_le_bytes(cls: Type, buffer: "Bytes") -> "U32": + """ + Converts a sequence of bytes into an arbitrarily sized unsigned integer + from its little endian representation. + """ + if len(buffer) > 4: + raise ValueError() + + return cls(int.from_bytes(buffer, "little")) + + def to_le_bytes4(self) -> "Bytes4": + """ + Converts this fixed sized unsigned integer into its little endian + representation, with exactly 4 bytes. + """ + return Bytes4(self.to_bytes(4, "little")) + + def to_le_bytes(self) -> "Bytes": + """ + Converts this fixed sized unsigned integer into its little endian + representation, in the fewest bytes possible. + """ + bit_length = self.bit_length() + byte_length = (bit_length + 7) // 8 + return self.to_bytes(byte_length, "little") + + +U32.MAX_VALUE = int.__new__(U32, (2**32) - 1) + + +class U64(FixedUint): + """ + Unsigned positive integer, which can represent `0` to `2 ** 64 - 1`, + inclusive. + """ + + MAX_VALUE: ClassVar["U64"] + """ + Largest value that can be represented by this integer type. + """ + + __slots__ = () + + @classmethod + def from_le_bytes(cls: Type, buffer: "Bytes") -> "U64": + """ + Converts a sequence of bytes into an arbitrarily sized unsigned integer + from its little endian representation. + """ + if len(buffer) > 8: + raise ValueError() + + return cls(int.from_bytes(buffer, "little")) + + def to_le_bytes8(self) -> "Bytes8": + """ + Converts this fixed sized unsigned integer into its little endian + representation, with exactly 8 bytes. + """ + return Bytes8(self.to_bytes(8, "little")) + + def to_le_bytes(self) -> "Bytes": + """ + Converts this fixed sized unsigned integer into its little endian + representation, in the fewest bytes possible. + """ + bit_length = self.bit_length() + byte_length = (bit_length + 7) // 8 + return self.to_bytes(byte_length, "little") + + @classmethod + def from_be_bytes(cls: Type, buffer: "Bytes") -> "U64": + """ + Converts a sequence of bytes into an unsigned 64 bit integer from its + big endian representation. + """ + if len(buffer) > 8: + raise ValueError() + + return cls(int.from_bytes(buffer, "big")) + + +U64.MAX_VALUE = int.__new__(U64, (2**64) - 1) + + +B = TypeVar("B", bound="FixedBytes") + + +class FixedBytes(bytes): + """ + Superclass for fixed sized byte arrays. Not intended to be used directly, + but should be subclassed. + """ + + LENGTH: int + """ + Number of bytes in each instance of this class. + """ + + __slots__ = () + + def __new__(cls: Type[B], *args: Any, **kwargs: Any) -> B: + """ + Create a new instance, ensuring the result has the correct length. + """ + result = super(FixedBytes, cls).__new__(cls, *args, **kwargs) + if len(result) != cls.LENGTH: + raise ValueError( + f"expected {cls.LENGTH} bytes but got {len(result)}" + ) + return result + + +class Bytes0(FixedBytes): + """ + Byte array of exactly zero elements. + """ + + LENGTH = 0 + """ + Number of bytes in each instance of this class. + """ + + +class Bytes4(FixedBytes): + """ + Byte array of exactly four elements. + """ + + LENGTH = 4 + """ + Number of bytes in each instance of this class. + """ + + +class Bytes8(FixedBytes): + """ + Byte array of exactly eight elements. + """ + + LENGTH = 8 + """ + Number of bytes in each instance of this class. + """ + + +class Bytes20(FixedBytes): + """ + Byte array of exactly 20 elements. + """ + + LENGTH = 20 + """ + Number of bytes in each instance of this class. + """ + + +class Bytes32(FixedBytes): + """ + Byte array of exactly 32 elements. + """ + + LENGTH = 32 + """ + Number of bytes in each instance of this class. + """ + + +class Bytes48(FixedBytes): + """ + Byte array of exactly 48 elements. + """ + + LENGTH = 48 + + +class Bytes64(FixedBytes): + """ + Byte array of exactly 64 elements. + """ + + LENGTH = 64 + """ + Number of bytes in each instance of this class. + """ + + +class Bytes256(FixedBytes): + """ + Byte array of exactly 256 elements. + """ + + LENGTH = 256 + """ + Number of bytes in each instance of this class. + """ + + +Bytes = bytes +""" +Sequence of bytes (octets) of arbitrary length. +""" + + +def _setattr_function(self: Any, attr: str, value: Any) -> None: + if getattr(self, "_frozen", None): + raise Exception("Mutating frozen dataclasses is not allowed.") + else: + object.__setattr__(self, attr, value) + + +def _delattr_function(self: Any, attr: str) -> None: + if self._frozen: + raise Exception("Mutating frozen dataclasses is not allowed.") + else: + object.__delattr__(self, attr) + + +def _make_init_function(f: Callable) -> Callable: + def init_function(self: Any, *args: Any, **kwargs: Any) -> None: + will_be_frozen = kwargs.pop("_frozen", True) + object.__setattr__(self, "_frozen", False) + f(self, *args, **kwargs) + self._frozen = will_be_frozen + + return init_function + + +def slotted_freezable(cls: Any) -> Any: + """ + Monkey patches a dataclass so it can be frozen by setting `_frozen` to + `True` and uses `__slots__` for efficiency. + + Instances will be created frozen by default unless you pass `_frozen=False` + to `__init__`. + """ + cls.__slots__ = ("_frozen",) + tuple(cls.__annotations__) + cls.__init__ = _make_init_function(cls.__init__) + cls.__setattr__ = _setattr_function + cls.__delattr__ = _delattr_function + return type(cls)(cls.__name__, cls.__bases__, dict(cls.__dict__)) + + +S = TypeVar("S") + + +def modify(obj: S, f: Callable[[S], None]) -> S: + """ + Create a copy of `obj` (which must be [`@slotted_freezable`]), and modify + it by applying `f`. The returned copy will be frozen. + + [`@slotted_freezable`]: ref:ethereum.base_types.slotted_freezable + """ + assert is_dataclass(obj) + assert isinstance(obj, SlottedFreezable) + new_obj = replace(obj, _frozen=False) + f(new_obj) + new_obj._frozen = True + return new_obj +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/__init__.md b/docs/revm-python-spec/revm-verif/spec/berlin/__init__.md new file mode 100644 index 00000000..7a34eaf9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/__init__.md @@ -0,0 +1,15 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(12244000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/blocks.md b/docs/revm-python-spec/revm-verif/spec/berlin/blocks.md new file mode 100644 index 00000000..0e8d10af --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import LegacyTransaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Union[Bytes, LegacyTransaction], ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/bloom.md b/docs/revm-python-spec/revm-verif/spec/berlin/bloom.md new file mode 100644 index 00000000..e9022a76 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/fork.md b/docs/revm-python-spec/revm-verif/spec/berlin/fork.md new file mode 100644 index 00000000..7852e3e1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/fork.md @@ -0,0 +1,1106 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_ACCESS_LIST_ADDRESS_COST, + TX_ACCESS_LIST_STORAGE_KEY_COST, + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + AccessListTransaction, + LegacyTransaction, + Transaction, + decode_transaction, + encode_transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(2 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 +BOMB_DELAY_BLOCKS = 9000000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + parent_has_ommers, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, + chain_id: U64, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Union[Bytes, Receipt]: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + if isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(receipt) + else: + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Union[LegacyTransaction, Bytes], ...], + ommers: Tuple[Header, ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[ + Bytes, Optional[Union[Bytes, LegacyTransaction]] + ] = Trie(secured=False, default=None) + receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(map(decode_transaction, transactions)): + trie_set( + transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) + ) + + sender_address = check_transaction(tx, gas_available, chain_id) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + chain_id=chain_id, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + preaccessed_addresses = set() + preaccessed_storage_keys = set() + if isinstance(tx, AccessListTransaction): + for address, keys in tx.access_list: + preaccessed_addresses.add(address) + for key in keys: + preaccessed_storage_keys.add((address, key)) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + preaccessed_addresses=frozenset(preaccessed_addresses), + preaccessed_storage_keys=frozenset(preaccessed_storage_keys), + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + access_list_cost = 0 + if isinstance(tx, AccessListTransaction): + for _address, keys in tx.access_list: + access_list_cost += TX_ACCESS_LIST_ADDRESS_COST + access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + + return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + r, s = tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + ensure( + v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock + ) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_2930(tx) + ) + + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: Transaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def signing_hash_2930(tx: AccessListTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x01" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, + parent_has_ommers: bool, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max( + (2 if parent_has_ommers else 1) + - int(block_timestamp - parent_timestamp) // 9, + -99, + ) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/fork_types.md b/docs/revm-python-spec/revm-verif/spec/berlin/fork_types.md new file mode 100644 index 00000000..5345d905 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/state.md b/docs/revm-python-spec/revm-verif/spec/berlin/state.md new file mode 100644 index 00000000..d49bcdb5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/state.md @@ -0,0 +1,617 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + _created_accounts: Set[Address] = field(default_factory=set) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + del state._created_accounts + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def mark_account_created(state: State, address: Address) -> None: + """ + 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. + """ + state._created_accounts.add(address) + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) + + +def get_storage_original(state: State, address: Address, key: Bytes) -> U256: + """ + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + """ + # In the transaction where an account is created, its preexisting storage + # is ignored. + if address in state._created_accounts: + return U256(0) + + _, original_trie = state._snapshots[0] + original_account_trie = original_trie.get(address) + + if original_account_trie is None: + original_value = U256(0) + else: + original_value = trie_get(original_account_trie, key) + + assert isinstance(original_value, U256) + + return original_value +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/transactions.md b/docs/revm-python-spec/revm-verif/spec/berlin/transactions.md new file mode 100644 index 00000000..9218c10c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/transactions.md @@ -0,0 +1,98 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from .. import rlp +from ..base_types import ( + U64, + U256, + Bytes, + Bytes0, + Bytes32, + Uint, + slotted_freezable, +) +from ..exceptions import InvalidBlock +from ..utils.ensure import ensure +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 +TX_ACCESS_LIST_ADDRESS_COST = 2400 +TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 + + +@slotted_freezable +@dataclass +class LegacyTransaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class AccessListTransaction: + """ + The transaction type added in EIP-2930 to support access lists. + """ + + chain_id: U64 + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +Transaction = Union[LegacyTransaction, AccessListTransaction] + + +def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: + """ + Encode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, LegacyTransaction): + return tx + elif isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(tx) + else: + raise Exception(f"Unable to encode transaction of type {type(tx)}") + + +def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: + """ + Decode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, Bytes): + ensure(tx[0] == 1, InvalidBlock) + return rlp.decode_to(AccessListTransaction, tx[1:]) + else: + return tx +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/trie.md b/docs/revm-python-spec/revm-verif/spec/berlin/trie.md new file mode 100644 index 00000000..15b69d55 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.muir_glacier import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import LegacyTransaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, LegacyTransaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Union[LegacyTransaction, Bytes]], + Optional[Union[Receipt, Bytes]], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (LegacyTransaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `eth1spec.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/berlin/utils/__init__.md new file mode 100644 index 00000000..d519f592 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/utils/address.md b/docs/revm-python-spec/revm-verif/spec/berlin/utils/address.md new file mode 100644 index 00000000..78cbff5f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/utils/address.md @@ -0,0 +1,97 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this berlin version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.berlin.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/berlin/utils/hexadecimal.md new file mode 100644 index 00000000..f7c18595 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Berlin types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/utils/message.md b/docs/revm-python-spec/revm-verif/spec/berlin/utils/message.md new file mode 100644 index 00000000..f7b338b7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/utils/message.md @@ -0,0 +1,121 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/utils/message.py) + +```python +""" +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. +""" +from typing import FrozenSet, Optional, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Bytes32, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, + preaccessed_addresses: FrozenSet[Address] = frozenset(), + preaccessed_storage_keys: FrozenSet[ + Tuple[(Address, Bytes32)] + ] = frozenset(), +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.berlin.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + accessed_addresses = set() + accessed_addresses.add(current_target) + accessed_addresses.add(caller) + accessed_addresses.update(PRE_COMPILED_CONTRACTS.keys()) + accessed_addresses.update(preaccessed_addresses) + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + accessed_addresses=accessed_addresses, + accessed_storage_keys=set(preaccessed_storage_keys), + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/__init__.md new file mode 100644 index 00000000..4a6df5ee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/__init__.md @@ -0,0 +1,151 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U64, U256, Bytes, Bytes0, Bytes32, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + chain_id: U64 + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: int + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + evm.accessed_addresses.update(child_evm.accessed_addresses) + evm.accessed_storage_keys.update(child_evm.accessed_storage_keys) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/exceptions.md new file mode 100644 index 00000000..f856a518 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/exceptions.md @@ -0,0 +1,130 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class InvalidParameter(ExceptionalHalt): + """ + Raised when invalid parameters are passed. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/gas.md new file mode 100644 index 00000000..ce99071b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/gas.md @@ -0,0 +1,246 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_FAST_STEP = Uint(5) +GAS_BLAKE2_PER_ROUND = Uint(1) +GAS_COLD_SLOAD = Uint(2100) +GAS_COLD_ACCOUNT_ACCESS = Uint(2600) +GAS_WARM_ACCESS = Uint(100) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/__init__.md new file mode 100644 index 00000000..d9aa8406 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/__init__.md @@ -0,0 +1,358 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + CHAINID = 0x46 + SELFBALANCE = 0x47 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.CHAINID: block_instructions.chain_id, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SELFBALANCE: environment_instructions.self_balance, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/arithmetic.md new file mode 100644 index 00000000..93d93b58 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/bitwise.md new file mode 100644 index 00000000..7276367e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/block.md new file mode 100644 index 00000000..d4d15226 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/block.md @@ -0,0 +1,212 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def chain_id(evm: Evm) -> None: + """ + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.chain_id)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/comparison.md new file mode 100644 index 00000000..dba7c7b5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/control_flow.md new file mode 100644 index 00000000..7c0b94fa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/environment.md new file mode 100644 index 00000000..eab59160 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/environment.md @@ -0,0 +1,520 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BASE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_COPY, + GAS_FAST_STEP, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + GAS_WARM_ACCESS, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) + else: + evm.accessed_addresses.add(address) + charge_gas( + evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 + + +def self_balance(evm: Evm) -> None: + """ + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_FAST_STEP) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, evm.message.current_target).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/keccak.md new file mode 100644 index 00000000..a1fae74e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/log.md new file mode 100644 index 00000000..fea7aec0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/memory.md new file mode 100644 index 00000000..c024da2c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/stack.md new file mode 100644 index 00000000..4c6adf0b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/storage.md new file mode 100644 index 00000000..bbe01eb9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/storage.md @@ -0,0 +1,132 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.base_types import Uint +from ethereum.utils.ensure import ensure + +from ...state import get_storage, get_storage_original, set_storage +from .. import Evm +from ..exceptions import OutOfGasError, WriteInStaticContext +from ..gas import ( + GAS_CALL_STIPEND, + GAS_COLD_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + GAS_WARM_ACCESS, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + if (evm.message.current_target, key) in evm.accessed_storage_keys: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + charge_gas(evm, GAS_COLD_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + ensure(evm.gas_left > GAS_CALL_STIPEND, OutOfGasError) + + original_value = get_storage_original( + evm.env.state, evm.message.current_target, key + ) + current_value = get_storage(evm.env.state, evm.message.current_target, key) + + gas_cost = Uint(0) + + if (evm.message.current_target, key) not in evm.accessed_storage_keys: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + gas_cost += GAS_COLD_SLOAD + + if original_value == current_value and current_value != new_value: + if original_value == 0: + gas_cost += GAS_STORAGE_SET + else: + gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD + else: + gas_cost += GAS_WARM_ACCESS + + # Refund Counter Calculation + if current_value != new_value: + if original_value != 0 and current_value != 0 and new_value == 0: + # Storage is cleared for the first time in the transaction + evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND) + + if original_value != 0 and current_value == 0: + # Gas refund issued earlier to be reversed + evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND) + + if original_value == new_value: + # Storage slot being restored to its original value + if original_value == 0: + # Slot was originally empty and was SET earlier + evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + else: + # Slot was originally non-empty and was UPDATED earlier + evm.refund_counter += int( + GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS + ) + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/system.md new file mode 100644 index 00000000..29808402 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/instructions/system.md @@ -0,0 +1,680 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL_VALUE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_WARM_ACCESS, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + evm.accessed_addresses.add(contract_address) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + charge_gas( + evm, + GAS_CREATE + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + create_gas_cost = ( + Uint(0) + if is_account_alive(evm.env.state, to) or value == 0 + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if beneficiary not in evm.accessed_addresses: + evm.accessed_addresses.add(beneficiary) + gas_cost += GAS_COLD_ACCOUNT_ACCESS + + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/interpreter.md new file mode 100644 index 00000000..bba54810 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/interpreter.md @@ -0,0 +1,311 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + mark_account_created, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = U256(evm.refund_counter) + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.berlin.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + # In the previously mentioned edge case the preexisting storage is ignored + # for gas refund purposes. In order to do this we must track created + # accounts. + mark_account_created(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.berlin.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=0, + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + accessed_addresses=message.accessed_addresses, + accessed_storage_keys=message.accessed_storage_keys, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/memory.md new file mode 100644 index 00000000..041d6f19 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..9ab9bc06 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/__init__.md @@ -0,0 +1,44 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +BLAKE2F_ADDRESS = hex_to_address("0x09") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..6541f1d2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(150)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(6000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..753ff870 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,50 @@ +# ๐Ÿ blake2f.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/precompiled_contracts/blake2f.py) + +```python +""" +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +""" +from ethereum.crypto.blake2 import Blake2b +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import GAS_BLAKE2_PER_ROUND, charge_gas +from ..exceptions import InvalidParameter + + +def blake2f(evm: Evm) -> None: + """ + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + ensure(len(data) == 213, InvalidParameter) + + blake2b = Blake2b() + rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) + + charge_gas(evm, GAS_BLAKE2_PER_ROUND * rounds) + + # OPERATION + ensure(f in [0, 1], InvalidParameter) + + evm.output = blake2b.compress(rounds, h, m, t_0, t_1, f) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..8c4d4f48 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..72a09a42 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..332145f7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/mapping.md @@ -0,0 +1,52 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + BLAKE2F_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .blake2f import blake2f +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, + BLAKE2F_ADDRESS: blake2f, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..2792ea18 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/modexp.md @@ -0,0 +1,174 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = 3 + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = Uint.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + + charge_gas( + evm, + gas_cost(base_length, modulus_length, exp_length, exp_head), + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def complexity(base_length: U256, modulus_length: U256) -> Uint: + """ + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + """ + max_length = max(Uint(base_length), Uint(modulus_length)) + words = (max_length + 7) // 8 + return words**2 + + +def iterations(exponent_length: U256, exponent_head: Uint) -> Uint: + """ + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + """ + if exponent_length <= 32 and exponent_head == 0: + count = Uint(0) + elif exponent_length <= 32: + bit_length = Uint(exponent_head.bit_length()) + + if bit_length > 0: + bit_length -= 1 + + count = bit_length + else: + length_part = 8 * (Uint(exponent_length) - 32) + bits_part = Uint(exponent_head.bit_length()) + + if bits_part > 0: + bits_part -= 1 + + count = length_part + bits_part + + return max(count, Uint(1)) + + +def gas_cost( + base_length: U256, + modulus_length: U256, + exponent_length: U256, + exponent_head: Uint, +) -> Uint: + """ + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + """ + multiplication_complexity = complexity(base_length, modulus_length) + iteration_count = iterations(exponent_length, exponent_head) + cost = multiplication_complexity * iteration_count + cost //= GQUADDIVISOR + return max(Uint(200), cost) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..289ff37e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..6616c77d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/runtime.md new file mode 100644 index 00000000..14862b50 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/berlin/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/berlin/vm/stack.md new file mode 100644 index 00000000..54c4c165 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/berlin/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/berlin/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/__init__.md b/docs/revm-python-spec/revm-verif/spec/byzantium/__init__.md new file mode 100644 index 00000000..3a400a7e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/__init__.md @@ -0,0 +1,15 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(4370000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/blocks.md b/docs/revm-python-spec/revm-verif/spec/byzantium/blocks.md new file mode 100644 index 00000000..feea79fe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import Transaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Transaction, ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/bloom.md b/docs/revm-python-spec/revm-verif/spec/byzantium/bloom.md new file mode 100644 index 00000000..54615c2e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/fork.md b/docs/revm-python-spec/revm-verif/spec/byzantium/fork.md new file mode 100644 index 00000000..11f1c5eb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/fork.md @@ -0,0 +1,1036 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + Transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(3 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 +BOMB_DELAY_BLOCKS = 3000000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + parent_has_ommers, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, + chain_id: U64, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Receipt: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Transaction, ...], + ommers: Tuple[Header, ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[Bytes, Optional[Transaction]] = Trie( + secured=False, default=None + ) + receipts_trie: Trie[Bytes, Optional[Receipt]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(transactions): + trie_set(transactions_trie, rlp.encode(Uint(i)), tx) + + sender_address = check_transaction(tx, gas_available, chain_id) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + return Uint(TX_BASE_COST + data_cost + create_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + v, r, s = tx.v, tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if v == 27 or v == 28: + public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) + else: + ensure(v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: Transaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, + parent_has_ommers: bool, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max( + (2 if parent_has_ommers else 1) + - int(block_timestamp - parent_timestamp) // 9, + -99, + ) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/fork_types.md b/docs/revm-python-spec/revm-verif/spec/byzantium/fork_types.md new file mode 100644 index 00000000..80394746 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/fork_types.md @@ -0,0 +1,72 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/state.md b/docs/revm-python-spec/revm-verif/spec/byzantium/state.md new file mode 100644 index 00000000..8f2159b8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/state.md @@ -0,0 +1,558 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/transactions.md b/docs/revm-python-spec/revm-verif/spec/byzantium/transactions.md new file mode 100644 index 00000000..9754daf4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/transactions.md @@ -0,0 +1,39 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Union + +from ..base_types import U256, Bytes, Bytes0, Uint, slotted_freezable +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 68 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 + + +@slotted_freezable +@dataclass +class Transaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/trie.md b/docs/revm-python-spec/revm-verif/spec/byzantium/trie.md new file mode 100644 index 00000000..f2599b02 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.spurious_dragon import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import Transaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, Transaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Transaction], + Optional[Receipt], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (Transaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/byzantium/utils/__init__.md new file mode 100644 index 00000000..c6717df6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/utils/address.md b/docs/revm-python-spec/revm-verif/spec/byzantium/utils/address.md new file mode 100644 index 00000000..00852fc9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/utils/address.md @@ -0,0 +1,68 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this byzantium version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.byzantium.fork_types.Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/byzantium/utils/hexadecimal.md new file mode 100644 index 00000000..3331adab --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Byzantium types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/utils/message.md b/docs/revm-python-spec/revm-verif/spec/byzantium/utils/message.md new file mode 100644 index 00000000..9cf5e9a1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/utils/message.md @@ -0,0 +1,103 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/utils/message.py) + +```python +""" +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. +""" +from typing import Optional, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.byzantium.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/__init__.md new file mode 100644 index 00000000..187003a4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/__init__.md @@ -0,0 +1,144 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: U256 + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/exceptions.md new file mode 100644 index 00000000..d0824353 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/exceptions.md @@ -0,0 +1,122 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/gas.md new file mode 100644 index 00000000..1d6390f0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/gas.md @@ -0,0 +1,245 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_SLOAD = Uint(200) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_EXTERNAL = Uint(700) +GAS_BALANCE = Uint(400) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_CALL = Uint(700) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/__init__.md new file mode 100644 index 00000000..71744195 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/__init__.md @@ -0,0 +1,344 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/arithmetic.md new file mode 100644 index 00000000..726dc424 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/bitwise.md new file mode 100644 index 00000000..711a3693 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/bitwise.md @@ -0,0 +1,160 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/block.md new file mode 100644 index 00000000..ba57a0b8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/block.md @@ -0,0 +1,189 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/comparison.md new file mode 100644 index 00000000..15126350 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/control_flow.md new file mode 100644 index 00000000..f27bfcd8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/environment.md new file mode 100644 index 00000000..3a03a6aa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/environment.md @@ -0,0 +1,444 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BALANCE, + GAS_BASE, + GAS_COPY, + GAS_EXTERNAL, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_BALANCE) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_EXTERNAL) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/keccak.md new file mode 100644 index 00000000..a62d9904 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/log.md new file mode 100644 index 00000000..c93143b1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/memory.md new file mode 100644 index 00000000..c1fb0207 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/stack.md new file mode 100644 index 00000000..0907b531 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/storage.md new file mode 100644 index 00000000..5eeabebc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/storage.md @@ -0,0 +1,92 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.utils.ensure import ensure + +from ...state import get_storage, set_storage +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + current_value = get_storage(evm.env.state, evm.message.current_target, key) + if new_value != 0 and current_value == 0: + gas_cost = GAS_STORAGE_SET + else: + gas_cost = GAS_STORAGE_UPDATE + + if new_value == 0 and current_value != 0: + evm.refund_counter += GAS_STORAGE_CLEAR_REFUND + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/system.md new file mode 100644 index 00000000..16da8f71 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/instructions/system.md @@ -0,0 +1,575 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import compute_contract_address, to_address +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL, + GAS_CALL_VALUE, + GAS_CREATE, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + push(evm.stack, U256(0)) + evm.gas_left += create_message_gas + elif account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + else: + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push( + evm.stack, U256.from_be_bytes(child_evm.message.current_target) + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + create_gas_cost = ( + Uint(0) + if value == 0 or is_account_alive(evm.env.state, to) + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/interpreter.md new file mode 100644 index 00000000..eacc38d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/interpreter.md @@ -0,0 +1,302 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = evm.refund_counter + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.byzantium.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by two `CREATE` calls collide. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.byzantium.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=U256(0), + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/memory.md new file mode 100644 index 00000000..d174dded --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..02cf5c58 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/__init__.md @@ -0,0 +1,43 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..62f81fc0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(500)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(40000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(80000 * (len(data) // 192) + 100000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..b6fe3476 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..4c915a18 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..584a64cf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/mapping.md @@ -0,0 +1,49 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..a0954a63 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/modexp.md @@ -0,0 +1,92 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = Uint(20) + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = U256.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + if exp_length < 32: + adjusted_exp_length = Uint(max(0, exp_head.bit_length() - 1)) + else: + adjusted_exp_length = Uint( + 8 * (int(exp_length) - 32) + max(0, exp_head.bit_length() - 1) + ) + + charge_gas( + evm, + ( + get_mult_complexity(Uint(max(base_length, modulus_length))) + * max(adjusted_exp_length, Uint(1)) + ) + // GQUADDIVISOR, + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def get_mult_complexity(x: Uint) -> Uint: + """ + Estimate the complexity of performing Karatsuba multiplication. + """ + if x <= 64: + return x**2 + elif x <= 1024: + return x**2 // 4 + 96 * x - 3072 + else: + return x**2 // 16 + 480 * x - 199680 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..7042abb0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..61e5b369 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/runtime.md new file mode 100644 index 00000000..c2273e18 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/byzantium/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/stack.md new file mode 100644 index 00000000..3ecad247 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/byzantium/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/byzantium/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/__init__.md b/docs/revm-python-spec/revm-verif/spec/cancun/__init__.md new file mode 100644 index 00000000..eb17ad2a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByTimestamp + +FORK_CRITERIA = ByTimestamp(1710338135) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/blocks.md b/docs/revm-python-spec/revm-verif/spec/cancun/blocks.md new file mode 100644 index 00000000..8d81fd79 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/blocks.md @@ -0,0 +1,111 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from ..base_types import ( + U64, + U256, + Bytes, + Bytes8, + Bytes32, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import LegacyTransaction + + +@slotted_freezable +@dataclass +class Withdrawal: + """ + Withdrawals that have been validated on the consensus layer. + """ + + index: U64 + validator_index: U64 + address: Address + amount: U256 + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + prev_randao: Bytes32 + nonce: Bytes8 + base_fee_per_gas: Uint + withdrawals_root: Root + blob_gas_used: U64 + excess_blob_gas: U64 + parent_beacon_block_root: Root + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Union[Bytes, LegacyTransaction], ...] + ommers: Tuple[Header, ...] + withdrawals: Tuple[Withdrawal, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/bloom.md b/docs/revm-python-spec/revm-verif/spec/cancun/bloom.md new file mode 100644 index 00000000..e8017568 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/fork.md b/docs/revm-python-spec/revm-verif/spec/cancun/fork.md new file mode 100644 index 00000000..c02aafad --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/fork.md @@ -0,0 +1,1155 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Tuple, Union + +from ethereum.base_types import Bytes0, Bytes32 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt, Withdrawal +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root, VersionedHash +from .state import ( + State, + TransientStorage, + account_exists_and_is_empty, + destroy_account, + destroy_touched_empty_accounts, + get_account, + increment_nonce, + process_withdrawal, + set_account_balance, + state_root, +) +from .transactions import ( + TX_ACCESS_LIST_ADDRESS_COST, + TX_ACCESS_LIST_STORAGE_KEY_COST, + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + AccessListTransaction, + BlobTransaction, + FeeMarketTransaction, + LegacyTransaction, + Transaction, + decode_transaction, + encode_transaction, +) +from .trie import Trie, root, trie_set +from .utils.hexadecimal import hex_to_address +from .utils.message import prepare_message +from .vm import Message +from .vm.gas import ( + calculate_blob_gas_price, + calculate_data_fee, + calculate_excess_blob_gas, + calculate_total_blob_gas, + init_code_cost, +) +from .vm.interpreter import MAX_CODE_SIZE, process_message_call + +BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 +ELASTICITY_MULTIPLIER = 2 +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) +SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") +BEACON_ROOTS_ADDRESS = hex_to_address( + "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" +) +SYSTEM_TRANSACTION_GAS = Uint(30000000) +MAX_BLOB_GAS_PER_BLOCK = 786432 +VERSIONED_HASH_VERSION_KZG = b"\x01" + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + excess_blob_gas = calculate_excess_blob_gas(parent_header) + ensure(block.header.excess_blob_gas == excess_blob_gas, InvalidBlock) + + validate_header(block.header, parent_header) + ensure(block.ommers == (), InvalidBlock) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + ensure( + apply_body_output.withdrawals_root == block.header.withdrawals_root, + InvalidBlock, + ) + ensure( + apply_body_output.blob_gas_used == block.header.blob_gas_used, + InvalidBlock, + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def calculate_base_fee_per_gas( + block_gas_limit: Uint, + parent_gas_limit: Uint, + parent_gas_used: Uint, + parent_base_fee_per_gas: Uint, +) -> Uint: + """ + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + """ + parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER + + ensure( + check_gas_limit(block_gas_limit, parent_gas_limit), + InvalidBlock, + ) + + if parent_gas_used == parent_gas_target: + expected_base_fee_per_gas = parent_base_fee_per_gas + elif parent_gas_used > parent_gas_target: + gas_used_delta = parent_gas_used - parent_gas_target + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = max( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, + 1, + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas + base_fee_per_gas_delta + ) + else: + gas_used_delta = parent_gas_target - parent_gas_used + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = ( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas - base_fee_per_gas_delta + ) + + return Uint(expected_base_fee_per_gas) + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.gas_used <= header.gas_limit, InvalidBlock) + + 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, + ) + + ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) + + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + ensure(header.difficulty == 0, InvalidBlock) + ensure(header.nonce == b"\x00\x00\x00\x00\x00\x00\x00\x00", InvalidBlock) + ensure(header.ommers_hash == EMPTY_OMMER_HASH, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + +def check_transaction( + state: State, + tx: Transaction, + gas_available: Uint, + chain_id: U64, + base_fee_per_gas: Uint, + excess_blob_gas: U64, +) -> Tuple[Address, Uint, Tuple[VersionedHash, ...]]: + """ + 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. + """ + if calculate_intrinsic_cost(tx) > tx.gas: + raise InvalidBlock + if tx.nonce >= 2**64 - 1: + raise InvalidBlock + if tx.to == Bytes0(b"") and len(tx.data) > 2 * MAX_CODE_SIZE: + raise InvalidBlock + + if tx.gas > gas_available: + raise InvalidBlock + + sender = recover_sender(chain_id, tx) + sender_account = get_account(state, sender) + + if isinstance(tx, (FeeMarketTransaction, BlobTransaction)): + if tx.max_fee_per_gas < tx.max_priority_fee_per_gas: + raise InvalidBlock + if tx.max_fee_per_gas < base_fee_per_gas: + raise InvalidBlock + + priority_fee_per_gas = min( + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas - base_fee_per_gas, + ) + effective_gas_price = priority_fee_per_gas + base_fee_per_gas + max_gas_fee = tx.gas * tx.max_fee_per_gas + else: + if tx.gas_price < base_fee_per_gas: + raise InvalidBlock + effective_gas_price = tx.gas_price + max_gas_fee = tx.gas * tx.gas_price + + if isinstance(tx, BlobTransaction): + if not isinstance(tx.to, Address): + raise InvalidBlock + if len(tx.blob_versioned_hashes) == 0: + raise InvalidBlock + for blob_versioned_hash in tx.blob_versioned_hashes: + if blob_versioned_hash[0:1] != VERSIONED_HASH_VERSION_KZG: + raise InvalidBlock + + if tx.max_fee_per_blob_gas < calculate_blob_gas_price(excess_blob_gas): + raise InvalidBlock + + max_gas_fee += calculate_total_blob_gas(tx) * tx.max_fee_per_blob_gas + blob_versioned_hashes = tx.blob_versioned_hashes + else: + blob_versioned_hashes = () + + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + return sender, effective_gas_price, blob_versioned_hashes + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Union[Bytes, Receipt]: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + if isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(receipt) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(receipt) + elif isinstance(tx, BlobTransaction): + return b"\x03" + rlp.encode(receipt) + else: + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + withdrawals_root : `ethereum.fork_types.Root` + Trie root of all the withdrawals in the block. + blob_gas_used : `ethereum.base_types.Uint` + Total blob gas used in the block. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + withdrawals_root: Root + blob_gas_used: Uint + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + base_fee_per_gas: Uint, + block_gas_limit: Uint, + block_time: U256, + prev_randao: Bytes32, + transactions: Tuple[Union[LegacyTransaction, Bytes], ...], + chain_id: U64, + withdrawals: Tuple[Withdrawal, ...], + parent_beacon_block_root: Root, + excess_blob_gas: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + prev_randao : + The previous randao from the beacon chain. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + withdrawals : + Withdrawals to be processed in the current block. + parent_beacon_block_root : + The root of the beacon block from the parent block. + excess_blob_gas : + Excess blob gas calculated from the previous block. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + blob_gas_used = Uint(0) + gas_available = block_gas_limit + transactions_trie: Trie[ + Bytes, Optional[Union[Bytes, LegacyTransaction]] + ] = Trie(secured=False, default=None) + receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( + secured=False, default=None + ) + withdrawals_trie: Trie[Bytes, Optional[Union[Bytes, Withdrawal]]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + beacon_block_roots_contract_code = get_account( + state, BEACON_ROOTS_ADDRESS + ).code + + system_tx_message = Message( + caller=SYSTEM_ADDRESS, + target=BEACON_ROOTS_ADDRESS, + gas=SYSTEM_TRANSACTION_GAS, + value=U256(0), + data=parent_beacon_block_root, + code=beacon_block_roots_contract_code, + depth=Uint(0), + current_target=BEACON_ROOTS_ADDRESS, + code_address=BEACON_ROOTS_ADDRESS, + should_transfer_value=False, + is_static=False, + accessed_addresses=set(), + accessed_storage_keys=set(), + parent_evm=None, + ) + + system_tx_env = vm.Environment( + caller=SYSTEM_ADDRESS, + origin=SYSTEM_ADDRESS, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + base_fee_per_gas=base_fee_per_gas, + gas_price=base_fee_per_gas, + time=block_time, + prev_randao=prev_randao, + state=state, + chain_id=chain_id, + traces=[], + excess_blob_gas=excess_blob_gas, + blob_versioned_hashes=(), + transient_storage=TransientStorage(), + ) + + system_tx_output = process_message_call(system_tx_message, system_tx_env) + + destroy_touched_empty_accounts( + system_tx_env.state, system_tx_output.touched_accounts + ) + + for i, tx in enumerate(map(decode_transaction, transactions)): + trie_set( + transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) + ) + + ( + sender_address, + effective_gas_price, + blob_versioned_hashes, + ) = check_transaction( + state, + tx, + gas_available, + chain_id, + base_fee_per_gas, + excess_blob_gas, + ) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + base_fee_per_gas=base_fee_per_gas, + gas_price=effective_gas_price, + time=block_time, + prev_randao=prev_randao, + state=state, + chain_id=chain_id, + traces=[], + excess_blob_gas=excess_blob_gas, + blob_versioned_hashes=blob_versioned_hashes, + transient_storage=TransientStorage(), + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + blob_gas_used += calculate_total_blob_gas(tx) + + ensure(blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK, InvalidBlock) + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + for i, wd in enumerate(withdrawals): + trie_set(withdrawals_trie, rlp.encode(Uint(i)), rlp.encode(wd)) + + process_withdrawal(state, wd) + + if account_exists_and_is_empty(state, wd.address): + destroy_account(state, wd.address) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + root(withdrawals_trie), + blob_gas_used, + ) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + sender = env.origin + sender_account = get_account(env.state, sender) + + if isinstance(tx, BlobTransaction): + blob_gas_fee = calculate_data_fee(env.excess_blob_gas, tx) + else: + blob_gas_fee = Uint(0) + + effective_gas_fee = tx.gas * env.gas_price + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + + sender_balance_after_gas_fee = ( + sender_account.balance - effective_gas_fee - blob_gas_fee + ) + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + preaccessed_addresses = set() + preaccessed_storage_keys = set() + preaccessed_addresses.add(env.coinbase) + if isinstance( + tx, (AccessListTransaction, FeeMarketTransaction, BlobTransaction) + ): + for address, keys in tx.access_list: + preaccessed_addresses.add(address) + for key in keys: + preaccessed_storage_keys.add((address, key)) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + preaccessed_addresses=frozenset(preaccessed_addresses), + preaccessed_storage_keys=frozenset(preaccessed_storage_keys), + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 5, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price + + # For non-1559 transactions env.gas_price == tx.gas_price + priority_fee_per_gas = env.gas_price - env.base_fee_per_gas + transaction_fee = ( + tx.gas - output.gas_left - gas_refund + ) * priority_fee_per_gas + + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + destroy_touched_empty_accounts(env.state, output.touched_accounts) + + return total_gas_used, output.logs, output.error + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + int(init_code_cost(Uint(len(tx.data)))) + else: + create_cost = 0 + + access_list_cost = 0 + if isinstance( + tx, (AccessListTransaction, FeeMarketTransaction, BlobTransaction) + ): + for _address, keys in tx.access_list: + access_list_cost += TX_ACCESS_LIST_ADDRESS_COST + access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + + return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + r, s = tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + ensure( + v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock + ) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_2930(tx) + ) + elif isinstance(tx, FeeMarketTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_1559(tx) + ) + elif isinstance(tx, BlobTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_4844(tx) + ) + + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def signing_hash_2930(tx: AccessListTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x01" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x02" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def signing_hash_4844(tx: BlobTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP-4844 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x03" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + tx.max_fee_per_blob_gas, + tx.blob_versioned_hashes, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/fork_types.md b/docs/revm-python-spec/revm-verif/spec/cancun/fork_types.md new file mode 100644 index 00000000..346fbcd4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/fork_types.md @@ -0,0 +1,74 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 +VersionedHash = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/state.md b/docs/revm-python-spec/revm-verif/spec/cancun/state.md new file mode 100644 index 00000000..ffc72085 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/state.md @@ -0,0 +1,719 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, Iterable, List, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .blocks import Withdrawal +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + created_accounts: Set[Address] = field(default_factory=set) + + +@dataclass +class TransientStorage: + """ + Contains all information that is preserved between message calls + within a transaction. + """ + + _tries: Dict[Address, Trie[Bytes, U256]] = field(default_factory=dict) + _snapshots: List[Dict[Address, Trie[Bytes, U256]]] = field( + default_factory=list + ) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + del state.created_accounts + + +def begin_transaction( + state: State, transient_storage: TransientStorage +) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + transient_storage._snapshots.append( + {k: copy_trie(t) for (k, t) in transient_storage._tries.items()} + ) + + +def commit_transaction( + state: State, transient_storage: TransientStorage +) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + transient_storage : TransientStorage + The transient storage of the transaction. + """ + state._snapshots.pop() + if not state._snapshots: + state.created_accounts.clear() + + transient_storage._snapshots.pop() + + +def rollback_transaction( + state: State, transient_storage: TransientStorage +) -> None: + """ + 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. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + if not state._snapshots: + state.created_accounts.clear() + + transient_storage._tries = transient_storage._snapshots.pop() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def mark_account_created(state: State, address: Address) -> None: + """ + 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. + """ + state.created_accounts.add(address) + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def process_withdrawal( + state: State, + wd: Withdrawal, +) -> None: + """ + Increase the balance of the withdrawing account. + """ + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += wd.amount * 10**9 + + modify_state(state, wd.address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def get_storage_original(state: State, address: Address, key: Bytes) -> U256: + """ + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + """ + # In the transaction where an account is created, its preexisting storage + # is ignored. + if address in state.created_accounts: + return U256(0) + + _, original_trie = state._snapshots[0] + original_account_trie = original_trie.get(address) + + if original_account_trie is None: + original_value = U256(0) + else: + original_value = trie_get(original_account_trie, key) + + assert isinstance(original_value, U256) + + return original_value + + +def get_transient_storage( + transient_storage: TransientStorage, address: Address, key: Bytes +) -> U256: + """ + Get a value at a storage key on an account from transient storage. + Returns `U256(0)` if the storage key has not been set previously. + Parameters + ---------- + transient_storage: `TransientStorage` + The transient storage + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + Returns + ------- + value : `U256` + Value at the key. + """ + trie = transient_storage._tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_transient_storage( + transient_storage: TransientStorage, + address: Address, + key: Bytes, + value: U256, +) -> None: + """ + 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. + """ + trie = transient_storage._tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + transient_storage._tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del transient_storage._tries[address] + + +def destroy_touched_empty_accounts( + state: State, touched_accounts: Iterable[Address] +) -> None: + """ + 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. + """ + for address in touched_accounts: + if account_exists_and_is_empty(state, address): + destroy_account(state, address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/transactions.md b/docs/revm-python-spec/revm-verif/spec/cancun/transactions.md new file mode 100644 index 00000000..ba5a442a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/transactions.md @@ -0,0 +1,156 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from .. import rlp +from ..base_types import ( + U64, + U256, + Bytes, + Bytes0, + Bytes32, + Uint, + slotted_freezable, +) +from ..exceptions import InvalidBlock +from .fork_types import Address, VersionedHash + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 +TX_ACCESS_LIST_ADDRESS_COST = 2400 +TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 + + +@slotted_freezable +@dataclass +class LegacyTransaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class AccessListTransaction: + """ + The transaction type added in EIP-2930 to support access lists. + """ + + chain_id: U64 + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class FeeMarketTransaction: + """ + The transaction type added in EIP-1559. + """ + + chain_id: U64 + nonce: U256 + max_priority_fee_per_gas: Uint + max_fee_per_gas: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class BlobTransaction: + """ + The transaction type added in EIP-4844. + """ + + chain_id: U64 + nonce: U256 + max_priority_fee_per_gas: Uint + max_fee_per_gas: Uint + gas: Uint + to: Address + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + max_fee_per_blob_gas: U256 + blob_versioned_hashes: Tuple[VersionedHash, ...] + y_parity: U256 + r: U256 + s: U256 + + +Transaction = Union[ + LegacyTransaction, + AccessListTransaction, + FeeMarketTransaction, + BlobTransaction, +] + + +def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: + """ + Encode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, LegacyTransaction): + return tx + elif isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(tx) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(tx) + elif isinstance(tx, BlobTransaction): + return b"\x03" + rlp.encode(tx) + else: + raise Exception(f"Unable to encode transaction of type {type(tx)}") + + +def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: + """ + Decode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, Bytes): + if tx[0] == 1: + return rlp.decode_to(AccessListTransaction, tx[1:]) + elif tx[0] == 2: + return rlp.decode_to(FeeMarketTransaction, tx[1:]) + elif tx[0] == 3: + return rlp.decode_to(BlobTransaction, tx[1:]) + else: + raise InvalidBlock + else: + return tx +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/trie.md b/docs/revm-python-spec/revm-verif/spec/cancun/trie.md new file mode 100644 index 00000000..7457ee42 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/trie.md @@ -0,0 +1,473 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.shanghai import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt, Withdrawal +from .fork_types import Account, Address, Root, encode_account +from .transactions import LegacyTransaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[ + Account, Bytes, LegacyTransaction, Receipt, Uint, U256, Withdrawal, None +] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Union[LegacyTransaction, Bytes]], + Optional[Union[Receipt, Bytes]], + Optional[Union[Withdrawal, Bytes]], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (LegacyTransaction, Receipt, Withdrawal, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/cancun/utils/__init__.md new file mode 100644 index 00000000..99017036 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/utils/address.md b/docs/revm-python-spec/revm-verif/spec/cancun/utils/address.md new file mode 100644 index 00000000..0b859601 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/utils/address.md @@ -0,0 +1,97 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this cancun version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.cancun.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/cancun/utils/hexadecimal.md new file mode 100644 index 00000000..1bbf4807 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Cancun types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/utils/message.md b/docs/revm-python-spec/revm-verif/spec/cancun/utils/message.md new file mode 100644 index 00000000..c4da7fd2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/utils/message.md @@ -0,0 +1,121 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/utils/message.py) + +```python +""" +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. +""" +from typing import FrozenSet, Optional, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Bytes32, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, + preaccessed_addresses: FrozenSet[Address] = frozenset(), + preaccessed_storage_keys: FrozenSet[ + Tuple[(Address, Bytes32)] + ] = frozenset(), +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.cancun.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + accessed_addresses = set() + accessed_addresses.add(current_target) + accessed_addresses.add(caller) + accessed_addresses.update(PRE_COMPILED_CONTRACTS.keys()) + accessed_addresses.update(preaccessed_addresses) + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + accessed_addresses=accessed_addresses, + accessed_storage_keys=set(preaccessed_storage_keys), + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/__init__.md new file mode 100644 index 00000000..955a3e2b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/__init__.md @@ -0,0 +1,155 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U64, U256, Bytes, Bytes0, Bytes32, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address, VersionedHash +from ..state import State, TransientStorage, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + base_fee_per_gas: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + prev_randao: Bytes32 + state: State + chain_id: U64 + traces: List[dict] + excess_blob_gas: U64 + blob_versioned_hashes: Tuple[VersionedHash, ...] + transient_storage: TransientStorage + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: int + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + evm.accessed_addresses.update(child_evm.accessed_addresses) + evm.accessed_storage_keys.update(child_evm.accessed_storage_keys) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/exceptions.md new file mode 100644 index 00000000..52141414 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/exceptions.md @@ -0,0 +1,146 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class InvalidParameter(ExceptionalHalt): + """ + Raised when invalid parameters are passed. + """ + + pass + + +class InvalidContractPrefix(ExceptionalHalt): + """ + Raised when the new contract code starts with 0xEF. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass + + +class KZGProofError(ExceptionalHalt): + """ + Raised when the point evaluation precompile can't verify a proof. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/gas.md new file mode 100644 index 00000000..8b05e084 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/gas.md @@ -0,0 +1,360 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U64, U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32, taylor_exponential + +from ..blocks import Header +from ..transactions import BlobTransaction, Transaction +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(4800) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_FAST_STEP = Uint(5) +GAS_BLAKE2_PER_ROUND = Uint(1) +GAS_COLD_SLOAD = Uint(2100) +GAS_COLD_ACCOUNT_ACCESS = Uint(2600) +GAS_WARM_ACCESS = Uint(100) +GAS_INIT_CODE_WORD_COST = 2 +GAS_BLOBHASH_OPCODE = Uint(3) +GAS_POINT_EVALUATION = Uint(50000) + +TARGET_BLOB_GAS_PER_BLOCK = U64(393216) +GAS_PER_BLOB = Uint(2**17) +MIN_BLOB_GASPRICE = Uint(1) +BLOB_GASPRICE_UPDATE_FRACTION = Uint(3338477) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) + + +def init_code_cost(init_code_length: Uint) -> Uint: + """ + Calculates the gas to be charged for the init code in CREAT* + opcodes as well as create transactions. + + Parameters + ---------- + init_code_length : + The length of the init code provided to the opcode + or a create transaction + + Returns + ------- + init_code_gas: `ethereum.base_types.Uint` + The gas to be charged for the init code. + """ + return GAS_INIT_CODE_WORD_COST * ceil32(init_code_length) // 32 + + +def calculate_excess_blob_gas(parent_header: Header) -> U64: + """ + Calculated the excess blob gas for the current block based + on the gas used in the parent block. + + Parameters + ---------- + parent_header : + The parent block of the current block. + + Returns + ------- + excess_blob_gas: `ethereum.base_types.U64` + The excess blob gas for the current block. + """ + parent_blob_gas = ( + parent_header.excess_blob_gas + parent_header.blob_gas_used + ) + if parent_blob_gas < TARGET_BLOB_GAS_PER_BLOCK: + return U64(0) + else: + return parent_blob_gas - TARGET_BLOB_GAS_PER_BLOCK + + +def calculate_total_blob_gas(tx: Transaction) -> Uint: + """ + Calculate the total blob gas for a transaction. + + Parameters + ---------- + tx : + The transaction for which the blob gas is to be calculated. + + Returns + ------- + total_blob_gas: `ethereum.base_types.Uint` + The total blob gas for the transaction. + """ + if isinstance(tx, BlobTransaction): + return GAS_PER_BLOB * len(tx.blob_versioned_hashes) + else: + return Uint(0) + + +def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: + """ + Calculate the blob gasprice for a block. + + Parameters + ---------- + excess_blob_gas : + The excess blob gas for the block. + + Returns + ------- + blob_gasprice: `Uint` + The blob gasprice. + """ + return taylor_exponential( + MIN_BLOB_GASPRICE, + Uint(excess_blob_gas), + BLOB_GASPRICE_UPDATE_FRACTION, + ) + + +def calculate_data_fee(excess_blob_gas: U64, tx: Transaction) -> Uint: + """ + Calculate the blob data fee for a transaction. + + Parameters + ---------- + excess_blob_gas : + The excess_blob_gas for the execution. + tx : + The transaction for which the blob data fee is to be calculated. + + Returns + ------- + data_fee: `Uint` + The blob data fee. + """ + return calculate_total_blob_gas(tx) * calculate_blob_gas_price( + excess_blob_gas + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/__init__.md new file mode 100644 index 00000000..5786ced9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/__init__.md @@ -0,0 +1,372 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + PREVRANDAO = 0x44 + GASLIMIT = 0x45 + CHAINID = 0x46 + SELFBALANCE = 0x47 + BASEFEE = 0x48 + BLOBHASH = 0x49 + BLOBBASEFEE = 0x4A + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + TLOAD = 0x5C + TSTORE = 0x5D + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH0 = 0x5F + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + MCOPY = 0x5E + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.PREVRANDAO: block_instructions.prev_randao, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.CHAINID: block_instructions.chain_id, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.MCOPY: memory_instructions.mcopy, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SELFBALANCE: environment_instructions.self_balance, + Ops.BASEFEE: environment_instructions.base_fee, + Ops.BLOBHASH: environment_instructions.blob_hash, + Ops.BLOBBASEFEE: environment_instructions.blob_base_fee, + Ops.SSTORE: storage_instructions.sstore, + Ops.TLOAD: storage_instructions.tload, + Ops.TSTORE: storage_instructions.tstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH0: stack_instructions.push0, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/arithmetic.md new file mode 100644 index 00000000..3357fce3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/bitwise.md new file mode 100644 index 00000000..3bf9c505 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/block.md new file mode 100644 index 00000000..b78ed6ef --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/block.md @@ -0,0 +1,254 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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`. + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def prev_randao(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.prev_randao)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def chain_id(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.chain_id)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/comparison.md new file mode 100644 index 00000000..05e15795 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/control_flow.md new file mode 100644 index 00000000..103f3d0e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/environment.md new file mode 100644 index 00000000..4e88c843 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/environment.md @@ -0,0 +1,596 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BASE, + GAS_BLOBHASH_OPCODE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_COPY, + GAS_FAST_STEP, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + GAS_WARM_ACCESS, + calculate_blob_gas_price, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) + else: + evm.accessed_addresses.add(address) + charge_gas( + evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 + + +def self_balance(evm: Evm) -> None: + """ + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_FAST_STEP) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, evm.message.current_target).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def base_fee(evm: Evm) -> None: + """ + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.base_fee_per_gas)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def blob_hash(evm: Evm) -> None: + """ + Pushes the versioned hash at a particular index on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOBHASH_OPCODE) + + # OPERATION + if index < len(evm.env.blob_versioned_hashes): + blob_hash = evm.env.blob_versioned_hashes[index] + else: + blob_hash = Bytes32(b"\x00" * 32) + push(evm.stack, U256.from_be_bytes(blob_hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def blob_base_fee(evm: Evm) -> None: + """ + Pushes the blob base fee on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + blob_base_fee = calculate_blob_gas_price(evm.env.excess_blob_gas) + push(evm.stack, U256(blob_base_fee)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/keccak.md new file mode 100644 index 00000000..9c944c6a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/log.md new file mode 100644 index 00000000..0a131355 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/memory.md new file mode 100644 index 00000000..be0bae0b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/memory.md @@ -0,0 +1,181 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes, Uint +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_COPY, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mcopy(evm: Evm) -> None: + """ + Copy the bytes in memory from one location to another. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + destination = pop(evm.stack) + source = pop(evm.stack) + length = pop(evm.stack) + + # GAS + words = ceil32(Uint(length)) // 32 + copy_gas_cost = GAS_COPY * words + + extend_memory = calculate_gas_extend_memory( + evm.memory, [(source, length), (destination, length)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = memory_read_bytes(evm.memory, source, length) + memory_write(evm.memory, destination, value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/stack.md new file mode 100644 index 00000000..267253e3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/stack.md @@ -0,0 +1,218 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + if num_bytes == 0: + charge_gas(evm, GAS_BASE) + else: + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push0 = partial(push_n, num_bytes=0) +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/storage.md new file mode 100644 index 00000000..66c15310 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/storage.md @@ -0,0 +1,188 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.base_types import Uint +from ethereum.utils.ensure import ensure + +from ...state import ( + get_storage, + get_storage_original, + get_transient_storage, + set_storage, + set_transient_storage, +) +from .. import Evm +from ..exceptions import OutOfGasError, WriteInStaticContext +from ..gas import ( + GAS_CALL_STIPEND, + GAS_COLD_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + GAS_WARM_ACCESS, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + if (evm.message.current_target, key) in evm.accessed_storage_keys: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + charge_gas(evm, GAS_COLD_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + ensure(evm.gas_left > GAS_CALL_STIPEND, OutOfGasError) + + original_value = get_storage_original( + evm.env.state, evm.message.current_target, key + ) + current_value = get_storage(evm.env.state, evm.message.current_target, key) + + gas_cost = Uint(0) + + if (evm.message.current_target, key) not in evm.accessed_storage_keys: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + gas_cost += GAS_COLD_SLOAD + + if original_value == current_value and current_value != new_value: + if original_value == 0: + gas_cost += GAS_STORAGE_SET + else: + gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD + else: + gas_cost += GAS_WARM_ACCESS + + # Refund Counter Calculation + if current_value != new_value: + if original_value != 0 and current_value != 0 and new_value == 0: + # Storage is cleared for the first time in the transaction + evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND) + + if original_value != 0 and current_value == 0: + # Gas refund issued earlier to be reversed + evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND) + + if original_value == new_value: + # Storage slot being restored to its original value + if original_value == 0: + # Slot was originally empty and was SET earlier + evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + else: + # Slot was originally non-empty and was UPDATED earlier + evm.refund_counter += int( + GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS + ) + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def tload(evm: Evm) -> None: + """ + 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. + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_WARM_ACCESS) + + # OPERATION + value = get_transient_storage( + evm.env.transient_storage, evm.message.current_target, key + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def tstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's transient storage. + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_WARM_ACCESS) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_transient_storage( + evm.env.transient_storage, evm.message.current_target, key, new_value + ) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/system.md new file mode 100644 index 00000000..601f9185 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/instructions/system.md @@ -0,0 +1,695 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + move_ether, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import OutOfGasError, Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL_VALUE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_WARM_ACCESS, + GAS_ZERO, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + init_code_cost, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, + init_code_gas: Uint, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import ( + MAX_CODE_SIZE, + STACK_DEPTH_LIMIT, + process_create_message, + ) + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + ensure(len(call_data) <= 2 * MAX_CODE_SIZE, OutOfGasError) + + evm.accessed_addresses.add(contract_address) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + init_code_gas = init_code_cost(Uint(memory_size)) + + charge_gas(evm, GAS_CREATE + extend_memory.cost + init_code_gas) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, + endowment, + contract_address, + memory_start_position, + memory_size, + init_code_gas, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + init_code_gas = init_code_cost(Uint(memory_size)) + charge_gas( + evm, + GAS_CREATE + + GAS_KECCAK256_WORD * call_data_words + + extend_memory.cost + + init_code_gas, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, + endowment, + contract_address, + memory_start_position, + memory_size, + init_code_gas, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + create_gas_cost = ( + Uint(0) + if is_account_alive(evm.env.state, to) or value == 0 + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if beneficiary not in evm.accessed_addresses: + evm.accessed_addresses.add(beneficiary) + gas_cost += GAS_COLD_ACCOUNT_ACCESS + + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + originator = evm.message.current_target + originator_balance = get_account(evm.env.state, originator).balance + + move_ether( + evm.env.state, + originator, + beneficiary, + originator_balance, + ) + + # register account for deletion only if it was created + # in the same transaction + if originator in evm.env.state.created_accounts: + # If beneficiary is the same as originator, then + # the ether is burnt. + set_account_balance(evm.env.state, originator, U256(0)) + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/interpreter.md new file mode 100644 index 00000000..617ed1cf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/interpreter.md @@ -0,0 +1,314 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + mark_account_created, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidContractPrefix, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Union[Tuple[()], Tuple[Log, ...]] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = U256(evm.refund_counter) + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.cancun.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state, env.transient_storage) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + # In the previously mentioned edge case the preexisting storage is ignored + # for gas refund purposes. In order to do this we must track created + # accounts. + mark_account_created(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + if len(contract_code) > 0: + ensure(contract_code[0] != 0xEF, InvalidContractPrefix) + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state, env.transient_storage) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state, env.transient_storage) + else: + rollback_transaction(env.state, env.transient_storage) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.cancun.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state, env.transient_storage) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state, env.transient_storage) + else: + commit_transaction(env.state, env.transient_storage) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=0, + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + accessed_addresses=message.accessed_addresses, + accessed_storage_keys=message.accessed_storage_keys, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/memory.md new file mode 100644 index 00000000..172c1ec3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..ca90d1d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/__init__.md @@ -0,0 +1,46 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", + "POINT_EVALUATION_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +BLAKE2F_ADDRESS = hex_to_address("0x09") +POINT_EVALUATION_ADDRESS = hex_to_address("0x0a") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..2e889eb2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(150)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(6000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..a18d9e7e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,50 @@ +# ๐Ÿ blake2f.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/blake2f.py) + +```python +""" +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +""" +from ethereum.crypto.blake2 import Blake2b +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import GAS_BLAKE2_PER_ROUND, charge_gas +from ..exceptions import InvalidParameter + + +def blake2f(evm: Evm) -> None: + """ + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + ensure(len(data) == 213, InvalidParameter) + + blake2b = Blake2b() + rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) + + charge_gas(evm, GAS_BLAKE2_PER_ROUND * rounds) + + # OPERATION + ensure(f in [0, 1], InvalidParameter) + + evm.output = blake2b.compress(rounds, h, m, t_0, t_1, f) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..1caca592 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..18014a48 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..57553ef4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/mapping.md @@ -0,0 +1,55 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + BLAKE2F_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + POINT_EVALUATION_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .blake2f import blake2f +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .point_evaluation import point_evaluation +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, + BLAKE2F_ADDRESS: blake2f, + POINT_EVALUATION_ADDRESS: point_evaluation, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..a6b133ea --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/modexp.md @@ -0,0 +1,174 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = 3 + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = Uint.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + + charge_gas( + evm, + gas_cost(base_length, modulus_length, exp_length, exp_head), + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def complexity(base_length: U256, modulus_length: U256) -> Uint: + """ + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + """ + max_length = max(Uint(base_length), Uint(modulus_length)) + words = (max_length + 7) // 8 + return words**2 + + +def iterations(exponent_length: U256, exponent_head: Uint) -> Uint: + """ + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + """ + if exponent_length <= 32 and exponent_head == 0: + count = Uint(0) + elif exponent_length <= 32: + bit_length = Uint(exponent_head.bit_length()) + + if bit_length > 0: + bit_length -= 1 + + count = bit_length + else: + length_part = 8 * (Uint(exponent_length) - 32) + bits_part = Uint(exponent_head.bit_length()) + + if bits_part > 0: + bits_part -= 1 + + count = length_part + bits_part + + return max(count, Uint(1)) + + +def gas_cost( + base_length: U256, + modulus_length: U256, + exponent_length: U256, + exponent_head: Uint, +) -> Uint: + """ + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + """ + multiplication_complexity = complexity(base_length, modulus_length) + iteration_count = iterations(exponent_length, exponent_head) + cost = multiplication_complexity * iteration_count + cost //= GQUADDIVISOR + return max(Uint(200), cost) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/point_evaluation.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/point_evaluation.md new file mode 100644 index 00000000..97c3bb55 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/point_evaluation.md @@ -0,0 +1,82 @@ +# ๐Ÿ point_evaluation.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/point_evaluation.py) + +```python +""" +Ethereum Virtual Machine (EVM) POINT EVALUATION PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the POINT EVALUATION precompiled contract. +""" +from eth2spec.deneb.mainnet import ( + KZGCommitment, + kzg_commitment_to_versioned_hash, + verify_kzg_proof, +) + +from ethereum.base_types import U256, Bytes +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.exceptions import KZGProofError +from ...vm.gas import GAS_POINT_EVALUATION, charge_gas + +FIELD_ELEMENTS_PER_BLOB = 4096 +BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 +VERSIONED_HASH_VERSION_KZG = b"\x01" + + +def point_evaluation(evm: Evm) -> None: + """ + 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. + + """ + data = evm.message.data + + ensure(len(data) == 192, KZGProofError) + + versioned_hash = data[:32] + z = data[32:64] + y = data[64:96] + commitment = KZGCommitment(data[96:144]) + proof = data[144:192] + + # GAS + charge_gas(evm, GAS_POINT_EVALUATION) + + # OPERATION + # Verify commitment matches versioned_hash + ensure( + kzg_commitment_to_versioned_hash(commitment) == versioned_hash, + KZGProofError, + ) + + # Verify KZG proof with z and y in big endian format + try: + kzg_proof_verification = verify_kzg_proof(commitment, z, y, proof) + except Exception as e: + raise KZGProofError from e + + ensure(kzg_proof_verification, KZGProofError) + + # Return FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded + # 32 byte big endian values + evm.output = Bytes( + U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes32() + + U256(BLS_MODULUS).to_be_bytes32() + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..6fa80413 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..755e09ec --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/runtime.md new file mode 100644 index 00000000..835546c4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/cancun/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/cancun/vm/stack.md new file mode 100644 index 00000000..0f56e995 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/cancun/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/cancun/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/__init__.md b/docs/revm-python-spec/revm-verif/spec/constantinople/__init__.md new file mode 100644 index 00000000..a34de381 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/__init__.md @@ -0,0 +1,15 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(7280000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/blocks.md b/docs/revm-python-spec/revm-verif/spec/constantinople/blocks.md new file mode 100644 index 00000000..9139ca01 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import Transaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Transaction, ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/bloom.md b/docs/revm-python-spec/revm-verif/spec/constantinople/bloom.md new file mode 100644 index 00000000..e62d60d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/fork.md b/docs/revm-python-spec/revm-verif/spec/constantinople/fork.md new file mode 100644 index 00000000..0c0ae0eb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/fork.md @@ -0,0 +1,1036 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + Transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(2 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 +BOMB_DELAY_BLOCKS = 5000000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + parent_has_ommers, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, + chain_id: U64, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Receipt: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Transaction, ...], + ommers: Tuple[Header, ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[Bytes, Optional[Transaction]] = Trie( + secured=False, default=None + ) + receipts_trie: Trie[Bytes, Optional[Receipt]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(transactions): + trie_set(transactions_trie, rlp.encode(Uint(i)), tx) + + sender_address = check_transaction(tx, gas_available, chain_id) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + return Uint(TX_BASE_COST + data_cost + create_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + v, r, s = tx.v, tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if v == 27 or v == 28: + public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) + else: + ensure(v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: Transaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, + parent_has_ommers: bool, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max( + (2 if parent_has_ommers else 1) + - int(block_timestamp - parent_timestamp) // 9, + -99, + ) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/fork_types.md b/docs/revm-python-spec/revm-verif/spec/constantinople/fork_types.md new file mode 100644 index 00000000..0e64c333 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/state.md b/docs/revm-python-spec/revm-verif/spec/constantinople/state.md new file mode 100644 index 00000000..2cdef16a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/state.md @@ -0,0 +1,558 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/transactions.md b/docs/revm-python-spec/revm-verif/spec/constantinople/transactions.md new file mode 100644 index 00000000..3e4b8f41 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/transactions.md @@ -0,0 +1,39 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Union + +from ..base_types import U256, Bytes, Bytes0, Uint, slotted_freezable +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 68 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 + + +@slotted_freezable +@dataclass +class Transaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/trie.md b/docs/revm-python-spec/revm-verif/spec/constantinople/trie.md new file mode 100644 index 00000000..07bae11b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.byzantium import trie as previous_trie +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import Transaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, Transaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Transaction], + Optional[Receipt], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (Transaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/constantinople/utils/__init__.md new file mode 100644 index 00000000..6051cead --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/utils/address.md b/docs/revm-python-spec/revm-verif/spec/constantinople/utils/address.md new file mode 100644 index 00000000..ae65b46a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/utils/address.md @@ -0,0 +1,96 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this constantinople version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.constantinople.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/constantinople/utils/hexadecimal.md new file mode 100644 index 00000000..132895d9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Constantinople types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/utils/message.md b/docs/revm-python-spec/revm-verif/spec/constantinople/utils/message.md new file mode 100644 index 00000000..7ea246b4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/utils/message.md @@ -0,0 +1,103 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/utils/message.py) + +```python +""" +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. +""" +from typing import Optional, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.constantinople.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/__init__.md new file mode 100644 index 00000000..2b24fabb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/__init__.md @@ -0,0 +1,144 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: U256 + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/exceptions.md new file mode 100644 index 00000000..bddc5fc3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/exceptions.md @@ -0,0 +1,122 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/gas.md new file mode 100644 index 00000000..586e0e49 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/gas.md @@ -0,0 +1,246 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_SLOAD = Uint(200) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_EXTERNAL = Uint(700) +GAS_BALANCE = Uint(400) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_CALL = Uint(700) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_CODE_HASH = Uint(400) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/__init__.md new file mode 100644 index 00000000..ce7cb8ff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/__init__.md @@ -0,0 +1,354 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/arithmetic.md new file mode 100644 index 00000000..f7575fcf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/bitwise.md new file mode 100644 index 00000000..05707c3c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/block.md new file mode 100644 index 00000000..1a415459 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/block.md @@ -0,0 +1,189 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/comparison.md new file mode 100644 index 00000000..6902ec82 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/control_flow.md new file mode 100644 index 00000000..f8d1a59c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/environment.md new file mode 100644 index 00000000..6f51f7ab --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/environment.md @@ -0,0 +1,475 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BALANCE, + GAS_BASE, + GAS_CODE_HASH, + GAS_COPY, + GAS_EXTERNAL, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_BALANCE) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_EXTERNAL) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_CODE_HASH) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/keccak.md new file mode 100644 index 00000000..f41d1c61 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/log.md new file mode 100644 index 00000000..5d4c229b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/memory.md new file mode 100644 index 00000000..e538b16d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/stack.md new file mode 100644 index 00000000..97c7f5ff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/storage.md new file mode 100644 index 00000000..433d26e0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/storage.md @@ -0,0 +1,92 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.utils.ensure import ensure + +from ...state import get_storage, set_storage +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + current_value = get_storage(evm.env.state, evm.message.current_target, key) + if new_value != 0 and current_value == 0: + gas_cost = GAS_STORAGE_SET + else: + gas_cost = GAS_STORAGE_UPDATE + + if new_value == 0 and current_value != 0: + evm.refund_counter += GAS_STORAGE_CLEAR_REFUND + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/system.md new file mode 100644 index 00000000..6b71634f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/instructions/system.md @@ -0,0 +1,641 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL, + GAS_CALL_VALUE, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + charge_gas( + evm, + GAS_CREATE + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + create_gas_cost = ( + Uint(0) + if value == 0 or is_account_alive(evm.env.state, to) + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/interpreter.md new file mode 100644 index 00000000..abd7f210 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/interpreter.md @@ -0,0 +1,303 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = evm.refund_counter + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.constantinople.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.constantinople.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=U256(0), + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/memory.md new file mode 100644 index 00000000..357b0193 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..76d8243f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/__init__.md @@ -0,0 +1,43 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..362f823e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(500)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(40000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(80000 * (len(data) // 192) + 100000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..151f2e7f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..e39f7653 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..77352809 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/mapping.md @@ -0,0 +1,49 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..3cb7c521 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/modexp.md @@ -0,0 +1,92 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = Uint(20) + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = U256.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + if exp_length < 32: + adjusted_exp_length = Uint(max(0, exp_head.bit_length() - 1)) + else: + adjusted_exp_length = Uint( + 8 * (int(exp_length) - 32) + max(0, exp_head.bit_length() - 1) + ) + + charge_gas( + evm, + ( + get_mult_complexity(Uint(max(base_length, modulus_length))) + * max(adjusted_exp_length, Uint(1)) + ) + // GQUADDIVISOR, + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def get_mult_complexity(x: Uint) -> Uint: + """ + Estimate the complexity of performing Karatsuba multiplication. + """ + if x <= 64: + return x**2 + elif x <= 1024: + return x**2 // 4 + 96 * x - 3072 + else: + return x**2 // 16 + 480 * x - 199680 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..10ba65b6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..9ee718e0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/runtime.md new file mode 100644 index 00000000..777b00e8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/constantinople/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/stack.md new file mode 100644 index 00000000..75ea60da --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/constantinople/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/constantinople/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/crypto/__init__.md b/docs/revm-python-spec/revm-verif/spec/crypto/__init__.md new file mode 100644 index 00000000..74d1318a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/crypto/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/crypto/__init__.py) + +```python +""" +Cryptographic primitives used in Ethereum. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/crypto/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/crypto/alt_bn128.md new file mode 100644 index 00000000..6f3e0845 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/crypto/alt_bn128.md @@ -0,0 +1,201 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/crypto/alt_bn128.py) + +```python +""" +The alt_bn128 curve +^^^^^^^^^^^^^^^^^^^ +""" + +from . import elliptic_curve, finite_field + +ALT_BN128_PRIME = 21888242871839275222246405745257275088696311157297823662689037894645226208583 # noqa: E501 +ALT_BN128_CURVE_ORDER = 21888242871839275222246405745257275088548364400416034343698204186575808495617 # noqa: E501 +ATE_PAIRING_COUNT = 29793968203157093289 +ATE_PAIRING_COUNT_BITS = 63 + + +class BNF(finite_field.PrimeField): + """ + The prime field over which the alt_bn128 curve is defined. + """ + + PRIME = ALT_BN128_PRIME + + +class BNP(elliptic_curve.EllipticCurve): + """ + The alt_bn128 curve. + """ + + FIELD = BNF + A = BNF(0) + B = BNF(3) + + +class BNF2(finite_field.GaloisField): + """ + `BNF` extended with a square root of 1 (`i`). + """ + + PRIME = ALT_BN128_PRIME + MODULUS = (1, 0) + + i: "BNF2" + i_plus_9: "BNF2" + + +BNF2.FROBENIUS_COEFFICIENTS = BNF2.calculate_frobenius_coefficients() +"""autoapi_noindex""" + +BNF2.i = BNF2((0, 1)) +"""autoapi_noindex""" + +BNF2.i_plus_9 = BNF2((9, 1)) +"""autoapi_noindex""" + + +class BNP2(elliptic_curve.EllipticCurve): + """ + A twist of `BNP`. This is actually the same curve as `BNP` under a change + of variable, but that change of variable is only possible over the larger + field `BNP12`. + """ + + FIELD = BNF2 + A = BNF2.zero() + B = BNF2.from_int(3) / (BNF2.i + BNF2.from_int(9)) + + +class BNF12(finite_field.GaloisField): + """ + `BNF2` extended by adding a 6th root of `9 + i` called `w` (omega). + """ + + PRIME = ALT_BN128_PRIME + MODULUS = (82, 0, 0, 0, 0, 0, -18, 0, 0, 0, 0, 0) + + w: "BNF12" + i_plus_9: "BNF12" + + def __mul__(self: "BNF12", right: "BNF12") -> "BNF12": # type: ignore[override] # noqa: E501 + """ + Multiplication special cased for BNF12. + """ + mul = [0] * 23 + + for i in range(12): + for j in range(12): + mul[i + j] += self[i] * right[j] + + for i in range(22, 11, -1): + mul[i - 6] -= mul[i] * (-18) + mul[i - 12] -= mul[i] * 82 + + return BNF12.__new__( + BNF12, + mul[:12], + ) + + +BNF12.FROBENIUS_COEFFICIENTS = BNF12.calculate_frobenius_coefficients() +"""autoapi_noindex""" + +BNF12.w = BNF12((0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) +"""autoapi_noindex""" + +BNF12.i_plus_9 = BNF12.w**6 +"""autoapi_noindex""" + + +class BNP12(elliptic_curve.EllipticCurve): + """ + The same curve as `BNP`, but defined over the larger field. This curve has + both subgroups of order `ALT_BN128_CURVE_ORDER` and allows pairings to be + computed. + """ + + FIELD = BNF12 + A = BNF12.zero() + B = BNF12.from_int(3) + + +def bnf2_to_bnf12(x: BNF2) -> BNF12: + """ + Lift a field element in `BNF2` to `BNF12`. + """ + return BNF12.from_int(x[0]) + BNF12.from_int(x[1]) * ( + BNF12.i_plus_9 - BNF12.from_int(9) + ) + + +def bnp_to_bnp12(p: BNP) -> BNP12: + """ + Lift a point from `BNP` to `BNP12`. + """ + return BNP12(BNF12.from_int(int(p.x)), BNF12.from_int(int(p.y))) + + +def twist(p: BNP2) -> BNP12: + """ + Apply to twist to change variables from the curve `BNP2` to `BNP12`. + """ + return BNP12( + bnf2_to_bnf12(p.x) * (BNF12.w**2), + bnf2_to_bnf12(p.y) * (BNF12.w**3), + ) + + +def linefunc(p1: BNP12, p2: BNP12, t: BNP12) -> BNF12: + """ + Evaluate the function defining the line between points `p1` and `p2` at the + point `t`. The mathematical significance of this function is that is has + divisor `(p1) + (p2) + (p1 + p2) - 3(O)`. + + Note: Abstract mathematical presentations of Miller's algorithm often + specify the divisor `(p1) + (p2) - (p1 + p2) - (O)`. This turns out not to + matter. + """ + if p1.x != p2.x: + lam = (p2.y - p1.y) / (p2.x - p1.x) + return lam * (t.x - p1.x) - (t.y - p1.y) + elif p1.y == p2.y: + lam = BNF12.from_int(3) * p1.x**2 / (BNF12.from_int(2) * p1.y) + return lam * (t.x - p1.x) - (t.y - p1.y) + else: + return t.x - p1.x + + +def miller_loop(q: BNP12, p: BNP12) -> BNF12: + """ + The core of the pairing algorithm. + """ + if p == BNP12.point_at_infinity() or q == BNP12.point_at_infinity(): + return BNF12.from_int(1) + r = q + f = BNF12.from_int(1) + for i in range(ATE_PAIRING_COUNT_BITS, -1, -1): + f = f * f * linefunc(r, r, p) + r = r.double() + if (ATE_PAIRING_COUNT - 1) & (2**i): + f = f * linefunc(r, q, p) + r = r + q + assert r == q.mul_by(ATE_PAIRING_COUNT - 1) + + q1 = BNP12(q.x.frobenius(), q.y.frobenius()) + nq2 = BNP12(q1.x.frobenius(), -q1.y.frobenius()) + + f = f * linefunc(r, q1, p) + r = r + q1 + f = f * linefunc(r, nq2, p) + + return f ** ((ALT_BN128_PRIME**12 - 1) // ALT_BN128_CURVE_ORDER) + + +def pairing(q: BNP2, p: BNP) -> BNF12: + """ + Compute the pairing of `q` and `p`. + """ + return miller_loop(twist(q), bnp_to_bnp12(p)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/crypto/blake2.md b/docs/revm-python-spec/revm-verif/spec/crypto/blake2.md new file mode 100644 index 00000000..c1a8da04 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/crypto/blake2.md @@ -0,0 +1,256 @@ +# ๐Ÿ blake2.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/crypto/blake2.py) + +```python +""" +The Blake2 Implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^ +""" +import struct +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import Uint + + +def spit_le_to_uint(data: bytes, start: int, num_words: int) -> List[Uint]: + """ + 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 + """ + words = [] + for i in range(num_words): + start_position = start + (i * 8) + words.append( + Uint.from_le_bytes(data[start_position : start_position + 8]) + ) + + return words + + +@dataclass +class Blake2: + """ + Implementation of the BLAKE2 cryptographic hashing algorithm. + + Please refer the following document for details: + https://datatracker.ietf.org/doc/html/rfc7693 + """ + + w: int + mask_bits: int + word_format: str + + R1: int + R2: int + R3: int + R4: int + + @property + def max_word(self) -> int: + """ + Largest value for a given Blake2 flavor. + """ + return 2**self.w + + @property + def w_R1(self) -> int: + """ + (w - R1) value for a given Blake2 flavor. + Used in the function G + """ + return self.w - self.R1 + + @property + def w_R2(self) -> int: + """ + (w - R2) value for a given Blake2 flavor. + Used in the function G + """ + return self.w - self.R2 + + @property + def w_R3(self) -> int: + """ + (w - R3) value for a given Blake2 flavor. + Used in the function G + """ + return self.w - self.R3 + + @property + def w_R4(self) -> int: + """ + (w - R4) value for a given Blake2 flavor. + Used in the function G + """ + return self.w - self.R4 + + sigma: Tuple = ( + (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), + (14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3), + (11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4), + (7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8), + (9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13), + (2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9), + (12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11), + (13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10), + (6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5), + (10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0), + ) + + IV: Tuple = ( + 0x6A09E667F3BCC908, + 0xBB67AE8584CAA73B, + 0x3C6EF372FE94F82B, + 0xA54FF53A5F1D36F1, + 0x510E527FADE682D1, + 0x9B05688C2B3E6C1F, + 0x1F83D9ABFB41BD6B, + 0x5BE0CD19137E2179, + ) + + @property + def sigma_len(self) -> int: + """ + Length of the sigma parameter. + """ + return len(self.sigma) + + def get_blake2_parameters(self, data: bytes) -> Tuple: + """ + Extract the parameters required in the Blake2 compression function + from the provided bytes data. + + Parameters + ---------- + data : + The bytes data that has been passed in the message. + """ + rounds = Uint.from_be_bytes(data[:4]) + h = spit_le_to_uint(data, 4, 8) + m = spit_le_to_uint(data, 68, 16) + t_0, t_1 = spit_le_to_uint(data, 196, 2) + f = Uint.from_be_bytes(data[212:]) + + return (rounds, h, m, t_0, t_1, f) + + def G( + self, v: List, a: int, b: int, c: int, d: int, x: int, y: int + ) -> List: + """ + The mixing function used in Blake2 + https://datatracker.ietf.org/doc/html/rfc7693#section-3.1 + + Parameters + ---------- + v : + The working vector to be mixed. + a, b, c, d : + Indexes within v of the words to be mixed. + x, y : + The two input words for the mixing. + """ + v[a] = (v[a] + v[b] + x) % self.max_word + v[d] = ((v[d] ^ v[a]) >> self.R1) ^ ( + (v[d] ^ v[a]) << self.w_R1 + ) % self.max_word + + v[c] = (v[c] + v[d]) % self.max_word + v[b] = ((v[b] ^ v[c]) >> self.R2) ^ ( + (v[b] ^ v[c]) << self.w_R2 + ) % self.max_word + + v[a] = (v[a] + v[b] + y) % self.max_word + v[d] = ((v[d] ^ v[a]) >> self.R3) ^ ( + (v[d] ^ v[a]) << self.w_R3 + ) % self.max_word + + v[c] = (v[c] + v[d]) % self.max_word + v[b] = ((v[b] ^ v[c]) >> self.R4) ^ ( + (v[b] ^ v[c]) << self.w_R4 + ) % self.max_word + + return v + + def compress( + self, + num_rounds: Uint, + h: List[Uint], + m: List[Uint], + t_0: Uint, + t_1: Uint, + f: bool, + ) -> bytes: + """ + 'F Compression' from section 3.2 of RFC 7693: + https://tools.ietf.org/html/rfc7693#section-3.2 + + Parameters + ---------- + num_rounds : + The number of rounds. A 32-bit unsigned big-endian word + h : + The state vector. 8 unsigned 64-bit little-endian words + m : + The message block vector. 16 unsigned 64-bit little-endian words + t_0, t_1 : + Offset counters. 2 unsigned 64-bit little-endian words + f: + The final block indicator flag. An 8-bit word + """ + # Initialize local work vector v[0..15] + v = [0] * 16 + v[0:8] = h # First half from state + v[8:15] = self.IV # Second half from IV + + v[12] = t_0 ^ self.IV[4] # Low word of the offset + v[13] = t_1 ^ self.IV[5] # High word of the offset + + if f: + v[14] = v[14] ^ self.mask_bits # Invert all bits for last block + + # Mixing + for r in range(num_rounds): + # for more than sigma_len rounds, the schedule + # wraps around to the beginning + s = self.sigma[r % self.sigma_len] + + v = self.G(v, 0, 4, 8, 12, m[s[0]], m[s[1]]) + v = self.G(v, 1, 5, 9, 13, m[s[2]], m[s[3]]) + v = self.G(v, 2, 6, 10, 14, m[s[4]], m[s[5]]) + v = self.G(v, 3, 7, 11, 15, m[s[6]], m[s[7]]) + v = self.G(v, 0, 5, 10, 15, m[s[8]], m[s[9]]) + v = self.G(v, 1, 6, 11, 12, m[s[10]], m[s[11]]) + v = self.G(v, 2, 7, 8, 13, m[s[12]], m[s[13]]) + v = self.G(v, 3, 4, 9, 14, m[s[14]], m[s[15]]) + + result_message_words = (h[i] ^ v[i] ^ v[i + 8] for i in range(8)) + return struct.pack("<8%s" % self.word_format, *result_message_words) + + +# Parameters specific to the Blake2b implementation +@dataclass +class Blake2b(Blake2): + """ + The Blake2b flavor (64-bits) of Blake2. + This version is used in the pre-compiled contract. + """ + + w: int = 64 + mask_bits: int = 0xFFFFFFFFFFFFFFFF + word_format: str = "Q" + + R1: int = 32 + R2: int = 24 + R3: int = 16 + R4: int = 63 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/crypto/elliptic_curve.md b/docs/revm-python-spec/revm-verif/spec/crypto/elliptic_curve.md new file mode 100644 index 00000000..df8e3a1c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/crypto/elliptic_curve.md @@ -0,0 +1,163 @@ +# ๐Ÿ elliptic_curve.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/crypto/elliptic_curve.py) + +```python +""" +Elliptic Curves +^^^^^^^^^^^^^^^ +""" + +from typing import Generic, Type, TypeVar + +import coincurve + +from ..base_types import U256, Bytes +from .finite_field import Field +from .hash import Hash32 + +SECP256K1N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 + +F = TypeVar("F", bound=Field) +T = TypeVar("T", bound="EllipticCurve") + + +def secp256k1_recover(r: U256, s: U256, v: U256, msg_hash: Hash32) -> Bytes: + """ + Recovers the public key from a given signature. + + Parameters + ---------- + r : + TODO + s : + TODO + v : + TODO + msg_hash : + Hash of the message being recovered. + + Returns + ------- + public_key : `ethereum.base_types.Bytes` + Recovered public key. + """ + r_bytes = r.to_be_bytes32() + s_bytes = s.to_be_bytes32() + + signature = bytearray([0] * 65) + signature[32 - len(r_bytes) : 32] = r_bytes + signature[64 - len(s_bytes) : 64] = s_bytes + signature[64] = v + public_key = coincurve.PublicKey.from_signature_and_message( + bytes(signature), msg_hash, hasher=None + ) + public_key = public_key.format(compressed=False)[1:] + return public_key + + +class EllipticCurve(Generic[F]): + """ + Superclass for integers modulo a prime. Not intended to be used + directly, but rather to be subclassed. + """ + + __slots__ = ("x", "y") + + FIELD: Type[F] + A: F + B: F + + x: F + y: F + + def __new__(cls: Type[T], x: F, y: F) -> T: + """ + Make new point on the curve. The point is not checked to see if it is + on the curve. + """ + res = object.__new__(cls) + res.x = x + res.y = y + return res + + def __init__(self, x: F, y: F) -> None: + """ + Checks if the point is on the curve. To skip this check call + `__new__()` directly. + """ + if ( + x != self.FIELD.zero() or y != self.FIELD.zero() + ) and y ** 2 - x**3 - self.A * x - self.B != self.FIELD.zero(): + raise ValueError("Point not on curve") + + def __eq__(self, other: object) -> bool: + """ + Test two points for equality. + """ + if not isinstance(other, type(self)): + return False + return self.x == other.x and self.y == other.y + + def __str__(self) -> str: + """ + Stringify a point as its coordinates. + """ + return str((self.x, self.y)) + + @classmethod + def point_at_infinity(cls: Type[T]) -> T: + """ + Return the point at infinity. This is the identity element of the group + operation. + + The point at infinity doesn't actually have coordinates so we use + `(0, 0)` (which isn't on the curve) to represent it. + """ + return cls.__new__(cls, cls.FIELD.zero(), cls.FIELD.zero()) + + def double(self: T) -> T: + """ + Add a point to itself. + """ + x, y, F = self.x, self.y, self.FIELD + if x == 0 and y == 0: + return self + lam = (F.from_int(3) * x**2 + self.A) / (F.from_int(2) * y) + new_x = lam**2 - x - x + new_y = lam * (x - new_x) - y + return self.__new__(type(self), new_x, new_y) + + def __add__(self: T, other: T) -> T: + """ + Add two points together. + """ + ZERO = self.FIELD.zero() + self_x, self_y, other_x, other_y = self.x, self.y, other.x, other.y + if self_x == ZERO and self_y == ZERO: + return other + if other_x == ZERO and other_y == ZERO: + return self + if self_x == other_x: + if self_y == other_y: + return self.double() + else: + return self.point_at_infinity() + lam = (other_y - self_y) / (other_x - self_x) + x = lam**2 - self_x - other_x + y = lam * (self_x - x) - self_y + return self.__new__(type(self), x, y) + + def mul_by(self: T, n: int) -> T: + """ + Multiply `self` by `n` using the double and add algorithm. + """ + res = self.__new__(type(self), self.FIELD.zero(), self.FIELD.zero()) + s = self + while n != 0: + if n % 2 == 1: + res = res + s + s = s + s + n //= 2 + return res +``` diff --git a/docs/revm-python-spec/revm-verif/spec/crypto/finite_field.md b/docs/revm-python-spec/revm-verif/spec/crypto/finite_field.md new file mode 100644 index 00000000..011762d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/crypto/finite_field.md @@ -0,0 +1,410 @@ +# ๐Ÿ finite_field.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/crypto/finite_field.py) + +```python +""" +Finite Fields +^^^^^^^^^^^^^ +""" + +# flake8: noqa: D102, D105 + +from typing import Iterable, List, Tuple, Type, TypeVar, cast + +from typing_extensions import Protocol + +from ..base_types import Bytes, Bytes32 + +F = TypeVar("F", bound="Field") + + +class Field(Protocol): + """ + A type protocol for defining fields. + """ + + __slots__ = () + + @classmethod + def zero(cls: Type[F]) -> F: + ... + + @classmethod + def from_int(cls: Type[F], n: int) -> F: + ... + + def __radd__(self: F, left: F) -> F: + ... + + def __add__(self: F, right: F) -> F: + ... + + def __iadd__(self: F, right: F) -> F: + ... + + def __sub__(self: F, right: F) -> F: + ... + + def __rsub__(self: F, left: F) -> F: + ... + + def __mul__(self: F, right: F) -> F: + ... + + def __rmul__(self: F, left: F) -> F: + ... + + def __imul__(self: F, right: F) -> F: + ... + + def __pow__(self: F, exponent: int) -> F: + ... + + def __ipow__(self: F, right: int) -> F: + ... + + def __neg__(self: F) -> F: + ... + + def __truediv__(self: F, right: F) -> F: + ... + + +T = TypeVar("T", bound="PrimeField") + + +class PrimeField(int, Field): + """ + Superclass for integers modulo a prime. Not intended to be used + directly, but rather to be subclassed. + """ + + __slots__ = () + PRIME: int + + @classmethod + def from_be_bytes(cls: Type[T], buffer: "Bytes") -> T: + """ + Converts a sequence of bytes into a element of the field. + Parameters + ---------- + buffer : + Bytes to decode. + Returns + ------- + self : `T` + Unsigned integer decoded from `buffer`. + """ + return cls(int.from_bytes(buffer, "big")) + + @classmethod + def zero(cls: Type[T]) -> T: + return cls.__new__(cls, 0) + + @classmethod + def from_int(cls: Type[T], n: int) -> T: + return cls(n) + + def __new__(cls: Type[T], value: int) -> T: + return int.__new__(cls, value % cls.PRIME) + + def __radd__(self: T, left: T) -> T: # type: ignore[override] + return self.__add__(left) + + def __add__(self: T, right: T) -> T: # type: ignore[override] + if not isinstance(right, int): + return NotImplemented + + return self.__new__(type(self), int.__add__(self, right)) + + def __iadd__(self: T, right: T) -> T: # type: ignore[override] + return self.__add__(right) + + def __sub__(self: T, right: T) -> T: # type: ignore[override] + if not isinstance(right, int): + return NotImplemented + + return self.__new__(type(self), int.__sub__(self, right)) + + def __rsub__(self: T, left: T) -> T: # type: ignore[override] + if not isinstance(left, int): + return NotImplemented + + return self.__new__(type(self), int.__rsub__(self, left)) + + def __mul__(self: T, right: T) -> T: # type: ignore[override] + if not isinstance(right, int): + return NotImplemented + + return self.__new__(type(self), int.__mul__(self, right)) + + def __rmul__(self: T, left: T) -> T: # type: ignore[override] + return self.__mul__(left) + + def __imul__(self: T, right: T) -> T: # type: ignore[override] + return self.__mul__(right) + + __floordiv__ = None # type: ignore + __rfloordiv__ = None # type: ignore + __ifloordiv__ = None + __divmod__ = None # type: ignore + __rdivmod__ = None # type: ignore + + def __pow__(self: T, exponent: int) -> T: # type: ignore[override] + # For reasons that are unclear, self must be cast to int here under + # PyPy. + return self.__new__( + type(self), int.__pow__(int(self), exponent, self.PRIME) + ) + + __rpow__ = None # type: ignore + + def __ipow__(self: T, right: int) -> T: # type: ignore[override] + return self.__pow__(right) + + __and__ = None # type: ignore + __or__ = None # type: ignore + __xor__ = None # type: ignore + __rxor__ = None # type: ignore + __ixor__ = None + __rshift__ = None # type: ignore + __lshift__ = None # type: ignore + __irshift__ = None + __ilshift__ = None + + def __neg__(self: T) -> T: + return self.__new__(type(self), int.__neg__(self)) + + def __truediv__(self: T, right: T) -> T: # type: ignore[override] + return self * right.multiplicative_inverse() + + def multiplicative_inverse(self: T) -> T: + return self ** (-1) + + def to_be_bytes32(self) -> "Bytes32": + """ + Converts this arbitrarily sized unsigned integer into its big endian + representation with exactly 32 bytes. + Returns + ------- + big_endian : `Bytes32` + Big endian (most significant bits first) representation. + """ + return Bytes32(self.to_bytes(32, "big")) + + +U = TypeVar("U", bound="GaloisField") + + +class GaloisField(tuple, Field): + """ + Superclass for defining finite fields. Not intended to be used + directly, but rather to be subclassed. + + Fields are represented as `F_p[x]/(x^n + ...)` where the `MODULUS` is a + tuple of the non-leading coefficients of the defining polynomial. For + example `x^3 + 2x^2 + 3x + 4` is `(2, 3, 4)`. + + In practice the polynomial is likely to be be sparse and you should overload + the `__mul__()` function to take advantage of this fact. + """ + + __slots__ = () + + PRIME: int + MODULUS: Tuple[int, ...] + FROBENIUS_COEFFICIENTS: Tuple["GaloisField", ...] + + @classmethod + def zero(cls: Type[U]) -> U: + return cls.__new__(cls, [0] * len(cls.MODULUS)) + + @classmethod + def from_int(cls: Type[U], n: int) -> U: + return cls.__new__(cls, [n] + [0] * (len(cls.MODULUS) - 1)) + + def __new__(cls: Type[U], iterable: Iterable[int]) -> U: + self = tuple.__new__(cls, (x % cls.PRIME for x in iterable)) + assert len(self) == len(cls.MODULUS) + return self + + def __add__(self: U, right: U) -> U: # type: ignore[override] + if not isinstance(right, type(self)): + return NotImplemented + + return self.__new__( + type(self), + ( + x + y + for (x, y) in cast(Iterable[Tuple[int, int]], zip(self, right)) + ), + ) + + def __radd__(self: U, left: U) -> U: + return self.__add__(left) + + def __iadd__(self: U, right: U) -> U: # type: ignore[override] + return self.__add__(right) + + def __sub__(self: U, right: U) -> U: + if not isinstance(right, type(self)): + return NotImplemented + + x: int + y: int + return self.__new__( + type(self), + ( + x - y + for (x, y) in cast(Iterable[Tuple[int, int]], zip(self, right)) + ), + ) + + def __rsub__(self: U, left: U) -> U: + if not isinstance(left, type(self)): + return NotImplemented + + return self.__new__( + type(self), + ( + x - y + for (x, y) in cast(Iterable[Tuple[int, int]], zip(left, self)) + ), + ) + + def __mul__(self: U, right: U) -> U: # type: ignore[override] + modulus = self.MODULUS + degree = len(modulus) + prime = self.PRIME + mul = [0] * (degree * 2) + + for i in range(degree): + for j in range(degree): + mul[i + j] += self[i] * right[j] + + for i in range(degree * 2 - 1, degree - 1, -1): + for j in range(i - degree, i): + mul[j] -= (mul[i] * modulus[degree - (i - j)]) % prime + + return self.__new__( + type(self), + mul[:degree], + ) + + def __rmul__(self: U, left: U) -> U: # type: ignore[override] + return self.__mul__(left) + + def __imul__(self: U, right: U) -> U: # type: ignore[override] + return self.__mul__(right) + + def __truediv__(self: U, right: U) -> U: + return self * right.multiplicative_inverse() + + def __neg__(self: U) -> U: + return self.__new__(type(self), (-a for a in self)) + + def scalar_mul(self: U, x: int) -> U: + """ + Multiply a field element by a integer. This is faster than using + `from_int()` and field multiplication. + """ + return self.__new__(type(self), (x * n for n in self)) + + def deg(self: U) -> int: + """ + This is a support function for `multiplicative_inverse()`. + """ + for i in range(len(self.MODULUS) - 1, -1, -1): + if self[i] != 0: + return i + raise ValueError("deg() does not support zero") + + def multiplicative_inverse(self: U) -> U: + """ + Calculate the multiplicative inverse. Uses the Euclidean algorithm. + """ + x2: List[int] + p = self.PRIME + x1, f1 = list(self.MODULUS), [0] * len(self) + x2, f2, d2 = list(self), [1] + [0] * (len(self) - 1), self.deg() + q_0 = pow(x2[d2], -1, p) + for i in range(d2): + x1[i + len(x1) - d2] = (x1[i + len(x1) - d2] - q_0 * x2[i]) % p + f1[i + len(x1) - d2] = (f1[i + len(x1) - d2] - q_0 * f2[i]) % p + for i in range(len(self.MODULUS) - 1, -1, -1): + if x1[i] != 0: + d1 = i + break + while True: + if d1 == 0: + ans = f1 + q = pow(x1[0], -1, self.PRIME) + for i in range(len(ans)): + ans[i] *= q + break + elif d2 == 0: + ans = f2 + q = pow(x2[0], -1, self.PRIME) + for i in range(len(ans)): + ans *= q + break + if d1 < d2: + q = x2[d2] * pow(x1[d1], -1, self.PRIME) + for i in range(len(self.MODULUS) - (d2 - d1)): + x2[i + (d2 - d1)] = (x2[i + (d2 - d1)] - q * x1[i]) % p + f2[i + (d2 - d1)] = (f2[i + (d2 - d1)] - q * f1[i]) % p + while x2[d2] == 0: + d2 -= 1 + else: + q = x1[d1] * pow(x2[d2], -1, self.PRIME) + for i in range(len(self.MODULUS) - (d1 - d2)): + x1[i + (d1 - d2)] = (x1[i + (d1 - d2)] - q * x2[i]) % p + f1[i + (d1 - d2)] = (f1[i + (d1 - d2)] - q * f2[i]) % p + while x1[d1] == 0: + d1 -= 1 + return self.__new__(type(self), ans) + + def __pow__(self: U, exponent: int) -> U: + degree = len(self.MODULUS) + if exponent < 0: + self = self.multiplicative_inverse() + exponent = -exponent + + res = self.__new__(type(self), [1] + [0] * (degree - 1)) + s = self + while exponent != 0: + if exponent % 2 == 1: + res *= s + s *= s + exponent //= 2 + return res + + def __ipow__(self: U, right: int) -> U: + return self.__pow__(right) + + @classmethod + def calculate_frobenius_coefficients(cls: Type[U]) -> Tuple[U, ...]: + """ + Calculate the coefficients needed by `frobenius()`. + """ + coefficients = [] + for i in range(len(cls.MODULUS)): + x = [0] * len(cls.MODULUS) + x[i] = 1 + coefficients.append(cls.__new__(cls, x) ** cls.PRIME) + return tuple(coefficients) + + def frobenius(self: U) -> U: + """ + Returns `self ** p`. This function is known as the Frobenius + endomorphism and has many special mathematical properties. In + particular it is extremely cheap to compute compared to other + exponentiations. + """ + ans = self.from_int(0) + a: int + for i, a in enumerate(self): + ans += cast(U, self.FROBENIUS_COEFFICIENTS[i]).scalar_mul(a) + return ans +``` diff --git a/docs/revm-python-spec/revm-verif/spec/crypto/hash.md b/docs/revm-python-spec/revm-verif/spec/crypto/hash.md new file mode 100644 index 00000000..4d5a76eb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/crypto/hash.md @@ -0,0 +1,62 @@ +# ๐Ÿ hash.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/crypto/hash.py) + +```python +""" +Cryptographic Hash Functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Cryptographic hashing functions. +""" + +from Crypto.Hash import keccak + +from ..base_types import Bytes, Bytes32, Bytes64 + +Hash32 = Bytes32 +Hash64 = Bytes64 + + +def keccak256(buffer: Bytes) -> Hash32: + """ + Computes the keccak256 hash of the input `buffer`. + + Parameters + ---------- + buffer : + Input for the hashing function. + + Returns + ------- + hash : `ethereum.base_types.Hash32` + Output of the hash function. + """ + k = keccak.new(digest_bits=256) + return Hash32(k.update(buffer).digest()) + + +def keccak512(buffer: Bytes) -> Hash64: + """ + Computes the keccak512 hash of the input `buffer`. + + Parameters + ---------- + buffer : + Input for the hashing function. + + Returns + ------- + hash : `ethereum.base_types.Hash32` + Output of the hash function. + """ + k = keccak.new(digest_bits=512) + return Hash64(k.update(buffer).digest()) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/__init__.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/__init__.md new file mode 100644 index 00000000..8403a522 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/__init__.md @@ -0,0 +1,15 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(1920000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/blocks.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/blocks.md new file mode 100644 index 00000000..0c9c6d42 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import Transaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Transaction, ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + post_state: Root + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/bloom.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/bloom.md new file mode 100644 index 00000000..574d33a9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/dao.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/dao.md new file mode 100644 index 00000000..24f246fa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/dao.md @@ -0,0 +1,163 @@ +# ๐Ÿ dao.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/dao.py) + +```python +""" +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. +""" + +from .state import State, get_account, move_ether +from .utils.hexadecimal import hex_to_address + +DAO_ACCOUNTS = [ + hex_to_address(address) + for address in [ + "0xd4fe7bc31cedb7bfb8a345f31e668033056b2728", + "0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425", + "0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f", + "0xecd135fa4f61a655311e86238c92adcd779555d2", + "0x1975bd06d486162d5dc297798dfc41edd5d160a7", + "0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6", + "0x319f70bab6845585f412ec7724b744fec6095c85", + "0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936", + "0x5c8536898fbb74fc7445814902fd08422eac56d0", + "0x6966ab0d485353095148a2155858910e0965b6f9", + "0x779543a0491a837ca36ce8c635d6154e3c4911a6", + "0x2a5ed960395e2a49b1c758cef4aa15213cfd874c", + "0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5", + "0x9c50426be05db97f5d64fc54bf89eff947f0a321", + "0x200450f06520bdd6c527622a273333384d870efb", + "0xbe8539bfe837b67d1282b2b1d61c3f723966f049", + "0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb", + "0xf1385fb24aad0cd7432824085e42aff90886fef5", + "0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091", + "0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd", + "0x51e0ddd9998364a2eb38588679f0d2c42653e4a6", + "0x627a0a960c079c21c34f7612d5d230e01b4ad4c7", + "0xf0b1aa0eb660754448a7937c022e30aa692fe0c5", + "0x24c4d950dfd4dd1902bbed3508144a54542bba94", + "0x9f27daea7aca0aa0446220b98d028715e3bc803d", + "0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90", + "0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b", + "0x63ed5a272de2f6d968408b4acb9024f4cc208ebf", + "0x6f6704e5a10332af6672e50b3d9754dc460dfa4d", + "0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6", + "0x492ea3bb0f3315521c31f273e565b868fc090f17", + "0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00", + "0x9ea779f907f0b315b364b0cfc39a0fde5b02a416", + "0xceaeb481747ca6c540a000c1f3641f8cef161fa7", + "0xcc34673c6c40e791051898567a1222daf90be287", + "0x579a80d909f346fbfb1189493f521d7f48d52238", + "0xe308bd1ac5fda103967359b2712dd89deffb7973", + "0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c", + "0xac1ecab32727358dba8962a0f3b261731aad9723", + "0x4fd6ace747f06ece9c49699c7cabc62d02211f75", + "0x440c59b325d2997a134c2c7c60a8c61611212bad", + "0x4486a3d68fac6967006d7a517b889fd3f98c102b", + "0x9c15b54878ba618f494b38f0ae7443db6af648ba", + "0x27b137a85656544b1ccb5a0f2e561a5703c6a68f", + "0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241", + "0x23b75c2f6791eef49c69684db4c6c1f93bf49a50", + "0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b", + "0xb9637156d330c0d605a791f1c31ba5890582fe1c", + "0x6131c42fa982e56929107413a9d526fd99405560", + "0x1591fc0f688c81fbeb17f5426a162a7024d430c2", + "0x542a9515200d14b68e934e9830d91645a980dd7a", + "0xc4bbd073882dd2add2424cf47d35213405b01324", + "0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4", + "0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb", + "0x3ba4d81db016dc2890c81f3acec2454bff5aada5", + "0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab", + "0xe4ae1efdfc53b73893af49113d8694a057b9c0d1", + "0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5", + "0x0737a6b837f97f46ebade41b9bc3e1c509c85c53", + "0x97f43a37f595ab5dd318fb46e7a155eae057317a", + "0x52c5317c848ba20c7504cb2c8052abd1fde29d03", + "0x4863226780fe7c0356454236d3b1c8792785748d", + "0x5d2b2e6fcbe3b11d26b525e085ff818dae332479", + "0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c", + "0x057b56736d32b86616a10f619859c6cd6f59092a", + "0x9aa008f65de0b923a2a4f02012ad034a5e2e2192", + "0x304a554a310c7e546dfe434669c62820b7d83490", + "0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79", + "0x4deb0033bb26bc534b197e61d19e0733e5679784", + "0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a", + "0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b", + "0x4fa802324e929786dbda3b8820dc7834e9134a2a", + "0x9da397b9e80755301a3b32173283a91c0ef6c87e", + "0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6", + "0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9", + "0x5dc28b15dffed94048d73806ce4b7a4612a1d48f", + "0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76", + "0x12e626b0eebfe86a56d633b9864e389b45dcb260", + "0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7", + "0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5", + "0xd164b088bd9108b60d0ca3751da4bceb207b0782", + "0x6231b6d0d5e77fe001c2a460bd9584fee60d409b", + "0x1cba23d343a983e9b5cfd19496b9a9701ada385f", + "0xa82f360a8d3455c5c41366975bde739c37bfeb8a", + "0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339", + "0x005f5cee7a43331d5a3d3eec71305925a62f34b6", + "0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d", + "0xd131637d5275fd1a68a3200f4ad25c71a2a9522e", + "0xbc07118b9ac290e4622f5e77a0853539789effbe", + "0x47e7aa56d6bdf3f36be34619660de61275420af8", + "0xacd87e28b0c9d1254e868b81cba4cc20d9a32225", + "0xadf80daec7ba8dcf15392f1ac611fff65d94f880", + "0x5524c55fb03cf21f549444ccbecb664d0acad706", + "0x40b803a9abce16f50f36a77ba41180eb90023925", + "0xfe24cdd8648121a43a7c86d289be4dd2951ed49f", + "0x17802f43a0137c506ba92291391a8a8f207f487d", + "0x253488078a4edf4d6f42f113d1e62836a942cf1a", + "0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915", + "0xb136707642a4ea12fb4bae820f03d2562ebff487", + "0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940", + "0xf14c14075d6c4ed84b86798af0956deef67365b5", + "0xca544e5c4687d109611d0f8f928b53a25af72448", + "0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c", + "0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7", + "0x6d87578288b6cb5549d5076a207456a1f6a63dc0", + "0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e", + "0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6", + "0x2b3455ec7fedf16e646268bf88846bd7a2319bb2", + "0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a", + "0xd343b217de44030afaa275f54d31a9317c7f441e", + "0x84ef4b2357079cd7a7c69fd7a37cd0609a679106", + "0xda2fef9e4a3230988ff17df2165440f37e8b1708", + "0xf4c64518ea10f995918a454158c6b61407ea345c", + "0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97", + "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", + "0x807640a13483f8ac783c557fcdf27be11ea4ac7a", + ] +] + +DAO_RECOVERY = hex_to_address("0xbf4ed7b27f1d666546e30d74d50d173d20bca754") + + +def apply_dao(state: State) -> None: + """ + Apply the dao fork to the state. + + Parameters + ---------- + state : + State before applying the DAO Fork. + """ + for address in DAO_ACCOUNTS: + balance = get_account(state, address).balance + move_ether(state, address, DAO_RECOVERY, balance) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/fork.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/fork.md new file mode 100644 index 00000000..655ba6b0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/fork.md @@ -0,0 +1,994 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/fork.py) + +```python +""" +.. _dao-fork: + +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Bytes32, Uint +from . import FORK_CRITERIA, vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .dao import apply_dao +from .fork_types import Address, Bloom, Root +from .state import ( + State, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + Transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(5 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. + + The DAO-Fork occurred as a result of the `2016 DAO Hacks + `_ in which an + unknown entity managed to drain more than 3.6 million ether causing the + price of ether to drop by nearly 35%. This fork was the solution to the + hacks and manually reset the affected parties' accounts to their state + prior to the attack. This fork essentially rewrote the history of the + Ethereum network. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + apply_dao(old.state) + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + if ( + header.number >= FORK_CRITERIA.block_number + and header.number < FORK_CRITERIA.block_number + 10 + ): + ensure(header.extra_data == b"dao-hard-fork", InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + post_state: Bytes32, + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Receipt: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + post_state=post_state, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Transaction, ...], + ommers: Tuple[Header, ...], +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[Bytes, Optional[Transaction]] = Trie( + secured=False, default=None + ) + receipts_trie: Trie[Bytes, Optional[Receipt]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(transactions): + trie_set(transactions_trie, rlp.encode(Uint(i)), tx) + + sender_address = check_transaction(tx, gas_available) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + traces=[], + ) + + gas_used, logs = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, state_root(state), (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + return total_gas_used, output.logs + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + return Uint(TX_BASE_COST + data_cost + create_cost) + + +def recover_sender(tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + v, r, s = tx.v, tx.r, tx.s + + # if v > 28: + # v = v - (chain_id*2+8) + + ensure(v == 27 or v == 28, InvalidBlock) + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + return Address(keccak256(public_key)[12:32]) + + +def signing_hash(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in the signature. + + The values that are used to compute the signing hash set the rules for a + transaction. For example, signing over the gas sets a limit for the + amount of money that is allowed to be pulled out of the sender's account. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max(1 - int(block_timestamp - parent_timestamp) // 10, -99) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = (int(block_number) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/fork_types.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/fork_types.md new file mode 100644 index 00000000..6bcbba69 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/state.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/state.md new file mode 100644 index 00000000..21e052e5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/state.md @@ -0,0 +1,479 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/transactions.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/transactions.md new file mode 100644 index 00000000..6efc0125 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/transactions.md @@ -0,0 +1,39 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Union + +from ..base_types import U256, Bytes, Bytes0, Uint, slotted_freezable +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 68 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 + + +@slotted_freezable +@dataclass +class Transaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/trie.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/trie.md new file mode 100644 index 00000000..a4d3ac4b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.homestead import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import Transaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, Transaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Transaction], + Optional[Receipt], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (Transaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/__init__.md new file mode 100644 index 00000000..cbaf05c6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/address.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/address.md new file mode 100644 index 00000000..58e554e7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/address.md @@ -0,0 +1,67 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this Dao Fork version of specification. +""" +from typing import Union + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.dao_fork.fork_types.Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/hexadecimal.md new file mode 100644 index 00000000..5b33ebbc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/utils/hexadecimal.py) + +```python +""" +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. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/message.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/message.md new file mode 100644 index 00000000..7dfdb10c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/utils/message.md @@ -0,0 +1,97 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/utils/message.py) + +```python +""" +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. +""" +from typing import Optional, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.dao_fork.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/__init__.md new file mode 100644 index 00000000..c9707c4d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/__init__.md @@ -0,0 +1,120 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: U256 + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + error: Optional[Exception] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/exceptions.md new file mode 100644 index 00000000..be42e993 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/exceptions.md @@ -0,0 +1,93 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/gas.md new file mode 100644 index 00000000..339159d1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/gas.md @@ -0,0 +1,213 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from ..fork_types import Address +from ..state import State, account_exists +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_SLOAD = Uint(50) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(10) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_EXTERNAL = Uint(20) +GAS_BALANCE = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_CALL = Uint(40) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + state: State, gas: Uint, to: Address, value: U256 +) -> MessageCallGas: + """ + Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`. + + Parameters + ---------- + state : + The current state. + gas : + The amount of gas provided to the message-call. + to: + The address of the recipient account. + value: + The amount of `ETH` that needs to be transferred. + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + create_gas_cost = Uint(0) if account_exists(state, to) else GAS_NEW_ACCOUNT + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + cost = GAS_CALL + gas + create_gas_cost + transfer_gas_cost + stipend = gas if value == 0 else GAS_CALL_STIPEND + gas + return MessageCallGas(cost, stipend) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/__init__.md new file mode 100644 index 00000000..a18a6c46 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/__init__.md @@ -0,0 +1,336 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + SELFDESTRUCT = 0xFF + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/arithmetic.md new file mode 100644 index 00000000..06eaec59 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/bitwise.md new file mode 100644 index 00000000..4a56815d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/bitwise.md @@ -0,0 +1,160 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/block.md new file mode 100644 index 00000000..64734d47 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/block.md @@ -0,0 +1,189 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/comparison.md new file mode 100644 index 00000000..63d64939 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/control_flow.md new file mode 100644 index 00000000..d7e11f42 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/environment.md new file mode 100644 index 00000000..7c465c88 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/environment.md @@ -0,0 +1,381 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.utils.numeric import ceil32 + +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..gas import ( + GAS_BALANCE, + GAS_BASE, + GAS_COPY, + GAS_EXTERNAL, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_BALANCE) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_EXTERNAL) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/keccak.md new file mode 100644 index 00000000..aec0913e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/log.md new file mode 100644 index 00000000..371762ff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/log.md @@ -0,0 +1,91 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 + +from ...blocks import Log +from .. import Evm +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/memory.md new file mode 100644 index 00000000..4d602baf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/stack.md new file mode 100644 index 00000000..acfbfe33 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/storage.md new file mode 100644 index 00000000..40cd4143 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/storage.md @@ -0,0 +1,89 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" + +from ...state import get_storage, set_storage +from .. import Evm +from ..gas import ( + GAS_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + current_value = get_storage(evm.env.state, evm.message.current_target, key) + if new_value != 0 and current_value == 0: + gas_cost = GAS_STORAGE_SET + else: + gas_cost = GAS_STORAGE_UPDATE + + if new_value == 0 and current_value != 0: + evm.refund_counter += GAS_STORAGE_CLEAR_REFUND + + charge_gas(evm, gas_cost) + + # OPERATION + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/system.md new file mode 100644 index 00000000..f0824136 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/instructions/system.md @@ -0,0 +1,434 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint + +from ...fork_types import Address +from ...state import ( + account_has_code_or_nonce, + get_account, + increment_nonce, + set_account_balance, +) +from ...utils.address import compute_contract_address, to_address +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..gas import ( + GAS_CALL, + GAS_CREATE, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + create_message_gas = evm.gas_left + evm.gas_left = Uint(0) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + push(evm.stack, U256(0)) + evm.gas_left += create_message_gas + elif account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + else: + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push( + evm.stack, U256.from_be_bytes(child_evm.message.current_target) + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + evm.env.state, gas, to, value + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + evm.env.state, gas, to, value + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_ZERO + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + charge_gas(evm, GAS_CALL + gas + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + gas, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/interpreter.md new file mode 100644 index 00000000..0b6601ad --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/interpreter.md @@ -0,0 +1,271 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Union[Tuple[()], Tuple[Log, ...]] + accounts_to_delete: Set[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + refund_counter = evm.refund_counter + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.dao_fork.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.dao_fork.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=U256(0), + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + error=None, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/memory.md new file mode 100644 index 00000000..bb328149 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..047febf1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/__init__.md @@ -0,0 +1,34 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..db3b1591 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..1f70fb5a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..4338d11a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/mapping.md @@ -0,0 +1,39 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .ecrecover import ecrecover +from .identity import identity +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..61aadbb6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..1ee6cafa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/runtime.md new file mode 100644 index 00000000..934a790c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/stack.md new file mode 100644 index 00000000..36d6e3fb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/dao_fork/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/dao_fork/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/ethash.md b/docs/revm-python-spec/revm-verif/spec/ethash.md new file mode 100644 index 00000000..1a536b79 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/ethash.md @@ -0,0 +1,433 @@ +# ๐Ÿ ethash.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/./ethash.py) + +```python +""" +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 +""" + +from typing import Callable, Tuple, Union + +from ethereum.base_types import U32, Bytes8, Uint +from ethereum.crypto.hash import Hash32, Hash64, keccak256, keccak512 +from ethereum.utils.numeric import ( + is_prime, + le_bytes_to_uint32_sequence, + le_uint32_sequence_to_bytes, + le_uint32_sequence_to_uint, +) + +EPOCH_SIZE = 30000 +""" +Number of blocks before a dataset needs to be regenerated (known as an +"epoch".) See [`epoch`]. + +[`epoch`]: ref:ethereum.ethash.epoch +""" + +INITIAL_CACHE_SIZE = 2**24 +""" +Size of the cache (in bytes) during the first epoch. Each subsequent epoch's +cache roughly grows by [`CACHE_EPOCH_GROWTH_SIZE`] bytes. See [`cache_size`]. + +[`CACHE_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.CACHE_EPOCH_GROWTH_SIZE +[`cache_size`]: ref:ethereum.ethash.cache_size +""" + +CACHE_EPOCH_GROWTH_SIZE = 2**17 +""" +After the first epoch, the cache size grows by roughly this amount. See +[`cache_size`]. + +[`cache_size`]: ref:ethereum.ethash.cache_size +""" + +INITIAL_DATASET_SIZE = 2**30 +""" +Size of the dataset (in bytes) during the first epoch. Each subsequent epoch's +dataset roughly grows by [`DATASET_EPOCH_GROWTH_SIZE`] bytes. See +[`dataset_size`]. + +[`DATASET_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE +[`dataset_size`]: ref:ethereum.ethash.dataset_size +""" + +DATASET_EPOCH_GROWTH_SIZE = 2**23 +""" +After the first epoch, the dataset size grows by roughly this amount. See +[`dataset_size`]. + +[`dataset_size`]: ref:ethereum.ethash.dataset_size +""" + +HASH_BYTES = 64 +""" +Length of a hash, in bytes. +""" + +MIX_BYTES = 128 +""" +Width of mix, in bytes. See [`generate_dataset_item`]. + +[`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item +""" + +CACHE_ROUNDS = 3 +""" +Number of times to repeat the [`keccak512`] step while generating the hash. See +[`generate_cache`]. + +[`keccak512`]: ref:ethereum.crypto.hash.keccak512 +[`generate_cache`]: ref:ethereum.ethash.generate_cache +""" + +DATASET_PARENTS = 256 +""" +Number of parents of each dataset element. See [`generate_dataset_item`]. + +[`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item +""" + +HASHIMOTO_ACCESSES = 64 +""" +Number of accesses in the [`hashimoto`] loop. + +[`hashimoto`]: ref:ethereum.ethash.hashimoto +""" + + +def epoch(block_number: Uint) -> Uint: + """ + Obtain the epoch number to which the block identified by `block_number` + belongs. The first epoch is numbered zero. + + An Ethash epoch is a fixed number of blocks ([`EPOCH_SIZE`]) long, during + which the dataset remains constant. At the end of each epoch, the dataset + is generated anew. See [`generate_dataset`]. + + [`EPOCH_SIZE`]: ref:ethereum.ethash.EPOCH_SIZE + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + """ + return block_number // EPOCH_SIZE + + +def cache_size(block_number: Uint) -> Uint: + """ + Obtain the cache size (in bytes) of the epoch to which `block_number` + belongs. + + See [`INITIAL_CACHE_SIZE`] and [`CACHE_EPOCH_GROWTH_SIZE`] for the initial + size and linear growth rate, respectively. The cache is generated in + [`generate_cache`]. + + The actual cache size is smaller than simply multiplying + `CACHE_EPOCH_GROWTH_SIZE` by the epoch number to minimize the risk of + unintended cyclic behavior. It is defined as the highest prime number below + what linear growth would calculate. + + [`INITIAL_CACHE_SIZE`]: ref:ethereum.ethash.INITIAL_CACHE_SIZE + [`CACHE_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.CACHE_EPOCH_GROWTH_SIZE + [`generate_cache`]: ref:ethereum.ethash.generate_cache + """ + size = INITIAL_CACHE_SIZE + (CACHE_EPOCH_GROWTH_SIZE * epoch(block_number)) + size -= HASH_BYTES + while not is_prime(size // HASH_BYTES): + size -= 2 * HASH_BYTES + + return size + + +def dataset_size(block_number: Uint) -> Uint: + """ + Obtain the dataset size (in bytes) of the epoch to which `block_number` + belongs. + + See [`INITIAL_DATASET_SIZE`] and [`DATASET_EPOCH_GROWTH_SIZE`][ds] for the + initial size and linear growth rate, respectively. The complete dataset is + generated in [`generate_dataset`], while the slices used in verification + are generated in [`generate_dataset_item`]. + + The actual dataset size is smaller than simply multiplying + `DATASET_EPOCH_GROWTH_SIZE` by the epoch number to minimize the risk of + unintended cyclic behavior. It is defined as the highest prime number below + what linear growth would calculate. + + [`INITIAL_DATASET_SIZE`]: ref:ethereum.ethash.INITIAL_DATASET_SIZE + [ds]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item + """ + size = INITIAL_DATASET_SIZE + ( + DATASET_EPOCH_GROWTH_SIZE * epoch(block_number) + ) + size -= MIX_BYTES + while not is_prime(size // MIX_BYTES): + size -= 2 * MIX_BYTES + + return size + + +def generate_seed(block_number: Uint) -> Hash32: + """ + Obtain the cache generation seed for the block identified by + `block_number`. See [`generate_cache`]. + + [`generate_cache`]: ref:ethereum.ethash.generate_cache + """ + epoch_number = epoch(block_number) + + seed = b"\x00" * 32 + while epoch_number != 0: + seed = keccak256(seed) + epoch_number -= 1 + + return Hash32(seed) + + +def generate_cache(block_number: Uint) -> Tuple[Tuple[U32, ...], ...]: + """ + 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 + """ + seed = generate_seed(block_number) + cache_size_bytes = cache_size(block_number) + + cache_size_words = cache_size_bytes // HASH_BYTES + cache = [keccak512(seed)] + + for index in range(1, cache_size_words): + cache_item = keccak512(cache[index - 1]) + cache.append(cache_item) + + for _ in range(CACHE_ROUNDS): + for index in range(cache_size_words): + # Converting `cache_size_words` to int as `-1 + Uint(5)` is an + # error. + first_cache_item = cache[ + (index - 1 + int(cache_size_words)) % cache_size_words + ] + second_cache_item = cache[ + U32.from_le_bytes(cache[index][0:4]) % cache_size_words + ] + result = bytes( + [a ^ b for a, b in zip(first_cache_item, second_cache_item)] + ) + cache[index] = keccak512(result) + + return tuple( + le_bytes_to_uint32_sequence(cache_item) for cache_item in cache + ) + + +def fnv(a: Union[Uint, U32], b: Union[Uint, U32]) -> U32: + """ + A non-associative substitute for XOR, inspired by the [FNV] hash by Fowler, + Noll, and Vo. See [`fnv_hash`], [`generate_dataset_item`], and + [`hashimoto`]. + + Note that here we multiply the prime with the full 32-bit input, in + contrast with the [FNV-1] spec which multiplies the prime with one byte + (octet) in turn. + + [`hashimoto`]: ref:ethereum.ethash.hashimoto + [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item + [`fnv_hash`]: ref:ethereum.ethash.fnv_hash + [FNV]: https://w.wiki/XKZ + [FNV-1]: http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1 + """ + # This is a faster way of doing `number % (2 ** 32)`. + result = ((Uint(a) * 0x01000193) ^ Uint(b)) & U32.MAX_VALUE + return U32(result) + + +def fnv_hash( + mix_integers: Tuple[U32, ...], data: Tuple[U32, ...] +) -> Tuple[U32, ...]: + """ + 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 + """ + return tuple( + fnv(mix_integers[i], data[i]) for i in range(len(mix_integers)) + ) + + +def generate_dataset_item( + cache: Tuple[Tuple[U32, ...], ...], index: Uint +) -> Hash64: + """ + Generate a particular dataset item 0-indexed by `index` by hashing + pseudorandomly-selected entries from `cache` together. See [`fnv`] and + [`fnv_hash`] for the digest function, [`generate_cache`] for generating + `cache`, and [`generate_dataset`] for the full dataset generation + algorithm. + + [`fnv`]: ref:ethereum.ethash.fnv + [`fnv_hash`]: ref:ethereum.ethash.fnv_hash + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + [`generate_cache`]: ref:ethereum.ethash.generate_cache + """ + mix = keccak512( + ( + le_uint32_sequence_to_uint(cache[index % len(cache)]) ^ index + ).to_le_bytes(number_bytes=HASH_BYTES) + ) + + mix_integers = le_bytes_to_uint32_sequence(mix) + + for j in range(DATASET_PARENTS): + mix_word: U32 = mix_integers[j % 16] + cache_index = fnv(index ^ j, mix_word) % len(cache) + parent = cache[cache_index] + mix_integers = fnv_hash(mix_integers, parent) + + mix = Hash64(le_uint32_sequence_to_bytes(mix_integers)) + + return keccak512(mix) + + +def generate_dataset(block_number: Uint) -> Tuple[Hash64, ...]: + """ + 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. + """ + dataset_size_bytes: Uint = dataset_size(block_number) + cache: Tuple[Tuple[U32, ...], ...] = generate_cache(block_number) + + # TODO: Parallelize this later on if it adds value + return tuple( + generate_dataset_item(cache, Uint(index)) + for index in range(dataset_size_bytes // HASH_BYTES) + ) + + +def hashimoto( + header_hash: Hash32, + nonce: Bytes8, + dataset_size: Uint, + fetch_dataset_item: Callable[[Uint], Tuple[U32, ...]], +) -> Tuple[bytes, Hash32]: + """ + 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 + """ + nonce_le = bytes(reversed(nonce)) + seed_hash = keccak512(header_hash + nonce_le) + seed_head = U32.from_le_bytes(seed_hash[:4]) + + rows = dataset_size // 128 + mix = le_bytes_to_uint32_sequence(seed_hash) * (MIX_BYTES // HASH_BYTES) + + for i in range(HASHIMOTO_ACCESSES): + new_data: Tuple[U32, ...] = () + parent = fnv(i ^ seed_head, mix[i % len(mix)]) % rows + for j in range(MIX_BYTES // HASH_BYTES): + # Typecasting `parent` from U32 to Uint as 2*parent + j may + # overflow U32. + new_data += fetch_dataset_item(2 * Uint(parent) + j) + + mix = fnv_hash(mix, new_data) + + compressed_mix = [] + for i in range(0, len(mix), 4): + compressed_mix.append( + fnv(fnv(fnv(mix[i], mix[i + 1]), mix[i + 2]), mix[i + 3]) + ) + + mix_digest = le_uint32_sequence_to_bytes(compressed_mix) + result = keccak256(seed_hash + mix_digest) + + return mix_digest, result + + +def hashimoto_light( + header_hash: Hash32, + nonce: Bytes8, + cache: Tuple[Tuple[U32, ...], ...], + dataset_size: Uint, +) -> Tuple[bytes, Hash32]: + """ + 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 + """ + + def fetch_dataset_item(index: Uint) -> Tuple[U32, ...]: + item: Hash64 = generate_dataset_item(cache, index) + return le_bytes_to_uint32_sequence(item) + + return hashimoto(header_hash, nonce, dataset_size, fetch_dataset_item) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/exceptions.md b/docs/revm-python-spec/revm-verif/spec/exceptions.md new file mode 100644 index 00000000..e5fef4a3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/exceptions.md @@ -0,0 +1,44 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/./exceptions.py) + +```python +""" +Exceptions +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The Ethereum specification exception classes. +""" + + +class EthereumException(Exception): + """ + The base class from which all exceptions thrown by the specification during + normal operation derive. + """ + + +class InvalidBlock(EthereumException): + """ + Thrown when a block being processed is found to be invalid. + """ + + +class RLPDecodingError(InvalidBlock): + """ + Indicates that RLP decoding failed. + """ + + +class RLPEncodingError(EthereumException): + """ + Indicates that RLP encoding failed. + """ +``` diff --git a/docs/revm-python-spec/revm-verif/spec/fork_criteria.md b/docs/revm-python-spec/revm-verif/spec/fork_criteria.md new file mode 100644 index 00000000..c077e9ea --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/fork_criteria.md @@ -0,0 +1,142 @@ +# ๐Ÿ fork_criteria.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/./fork_criteria.py) + +```python +""" +Fork Criteria +^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Classes for specifying criteria for Mainnet forks. +""" + +import functools +from abc import ABC, abstractmethod +from typing import Final, Tuple + + +@functools.total_ordering +class ForkCriteria(ABC): + """ + Type that represents the condition required for a fork to occur. + """ + + BLOCK_NUMBER: Final[int] = 0 + TIMESTAMP: Final[int] = 1 + UNSCHEDULED: Final[int] = 2 + + _internal: Tuple[int, int] + + def __eq__(self, other: object) -> bool: + """ + Equality for fork criteria. + """ + if isinstance(other, ForkCriteria): + return self._internal == other._internal + return NotImplemented + + def __lt__(self, other: object) -> bool: + """ + Ordering for fork criteria. Block number forks are before timestamp + forks and scheduled forks are before unscheduled forks. + """ + if isinstance(other, ForkCriteria): + return self._internal < other._internal + return NotImplemented + + def __hash__(self) -> int: + """ + `ForkCriteria` is hashable, so it can be stored in dictionaries. + """ + return hash(self._internal) + + @abstractmethod + def check(self, block_number: int, timestamp: int) -> bool: + """ + Check whether fork criteria have been met. + """ + ... + + @abstractmethod + def __repr__(self) -> str: + """ + String representation of this object. + """ + raise NotImplementedError() + + +class ByBlockNumber(ForkCriteria): + """ + Forks that occur when a specific block number has been reached. + """ + + block_number: int + + def __init__(self, block_number: int): + self._internal = (ForkCriteria.BLOCK_NUMBER, block_number) + self.block_number = block_number + + def check(self, block_number: int, timestamp: int) -> bool: + """ + Check whether the block number has been reached. + """ + return block_number >= self.block_number + + def __repr__(self) -> str: + """ + String representation of this object. + """ + return f"ByBlockNumber({self.block_number})" + + +class ByTimestamp(ForkCriteria): + """ + Forks that occur when a specific timestamp has been reached. + """ + + timestamp: int + + def __init__(self, timestamp: int): + self._internal = (ForkCriteria.TIMESTAMP, timestamp) + self.timestamp = timestamp + + def check(self, block_number: int, timestamp: int) -> bool: + """ + Check whether the timestamp has been reached. + """ + return timestamp >= self.timestamp + + def __repr__(self) -> str: + """ + String representation of this object. + """ + return f"ByTimestamp({self.timestamp})" + + +class Unscheduled(ForkCriteria): + """ + Forks that have not been scheduled. + """ + + def __init__(self) -> None: + self._internal = (ForkCriteria.UNSCHEDULED, 0) + + def check(self, block_number: int, timestamp: int) -> bool: + """ + Unscheduled forks never occur. + """ + return False + + def __repr__(self) -> str: + """ + String representation of this object. + """ + return "Unscheduled()" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/__init__.md b/docs/revm-python-spec/revm-verif/spec/frontier/__init__.md new file mode 100644 index 00000000..d62384e9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/__init__.md @@ -0,0 +1,13 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/__init__.py) + +```python +""" +Frontier is the first production-ready iteration of the Ethereum protocol. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(0) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/blocks.md b/docs/revm-python-spec/revm-verif/spec/frontier/blocks.md new file mode 100644 index 00000000..631bd104 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import Transaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Transaction, ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + post_state: Root + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/bloom.md b/docs/revm-python-spec/revm-verif/spec/frontier/bloom.md new file mode 100644 index 00000000..67c71ccb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/fork.md b/docs/revm-python-spec/revm-verif/spec/frontier/fork.md new file mode 100644 index 00000000..a4f1326d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/fork.md @@ -0,0 +1,963 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple + +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Bytes32, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_BASE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + Transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(5 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + post_state: Bytes32, + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Receipt: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + post_state=post_state, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Transaction, ...], + ommers: Tuple[Header, ...], +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[Bytes, Optional[Transaction]] = Trie( + secured=False, default=None + ) + receipts_trie: Trie[Bytes, Optional[Receipt]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(transactions): + trie_set(transactions_trie, rlp.encode(Uint(i)), tx) + + sender_address = check_transaction(tx, gas_available) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + traces=[], + ) + + gas_used, logs = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, state_root(state), (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + return total_gas_used, output.logs + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + return Uint(TX_BASE_COST + data_cost) + + +def recover_sender(tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + v, r, s = tx.v, tx.r, tx.s + + # if v > 28: + # v = v - (chain_id*2+8) + + ensure(v == 27 or v == 28, InvalidBlock) + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s < SECP256K1N, InvalidBlock) + + public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + return Address(keccak256(public_key)[12:32]) + + +def signing_hash(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in the signature. + + The values that are used to compute the signing hash set the rules for a + transaction. For example, signing over the gas sets a limit for the + amount of money that is allowed to be pulled out of the sender's account. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, +) -> Uint: + """ + Computes difficulty of a block using its header and + parent header. + + The difficulty of a block is determined by the time the block was + created after its parent. If a block's timestamp is more than 13 + seconds after its parent block then its difficulty is set as the + difference between the parent's difficulty and the + ``max_adjustment_delta``. Otherwise, if the time between parent and + child blocks is too small (under 13 seconds) then, to avoid mass + forking, the block's difficulty is set to the sum of the delta and + the parent's difficulty. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + max_adjustment_delta = parent_difficulty // Uint(2048) + if block_timestamp < parent_timestamp + 13: + difficulty = parent_difficulty + max_adjustment_delta + else: # block_timestamp >= parent_timestamp + 13 + difficulty = parent_difficulty - max_adjustment_delta + + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = (int(block_number) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return max(difficulty, MINIMUM_DIFFICULTY) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/fork_types.md b/docs/revm-python-spec/revm-verif/spec/frontier/fork_types.md new file mode 100644 index 00000000..80251bf5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/state.md b/docs/revm-python-spec/revm-verif/spec/frontier/state.md new file mode 100644 index 00000000..4eb4e7db --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/state.md @@ -0,0 +1,479 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/transactions.md b/docs/revm-python-spec/revm-verif/spec/frontier/transactions.md new file mode 100644 index 00000000..80439043 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/transactions.md @@ -0,0 +1,38 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Union + +from ..base_types import U256, Bytes, Bytes0, Uint, slotted_freezable +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 68 +TX_DATA_COST_PER_ZERO = 4 + + +@slotted_freezable +@dataclass +class Transaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/trie.md b/docs/revm-python-spec/revm-verif/spec/frontier/trie.md new file mode 100644 index 00000000..aefe852b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/trie.md @@ -0,0 +1,471 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import Transaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, Transaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Transaction], + Optional[Receipt], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (Transaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + raise AssertionError( + f"encoding for {type(node)} is not currently implemented" + ) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/frontier/utils/__init__.md new file mode 100644 index 00000000..62fd4e89 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/utils/address.md b/docs/revm-python-spec/revm-verif/spec/frontier/utils/address.md new file mode 100644 index 00000000..486a3573 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/utils/address.md @@ -0,0 +1,67 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this frontier version of specification. +""" +from typing import Union + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.frontier.fork_types.Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/frontier/utils/hexadecimal.md new file mode 100644 index 00000000..fe28751c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Frontier +types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/utils/message.md b/docs/revm-python-spec/revm-verif/spec/frontier/utils/message.md new file mode 100644 index 00000000..f7a2f606 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/utils/message.md @@ -0,0 +1,93 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/utils/message.py) + +```python +""" +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. +""" +from typing import Optional, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + + Returns + ------- + message: `ethereum.frontier.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/__init__.md new file mode 100644 index 00000000..e9664ffd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/__init__.md @@ -0,0 +1,120 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: U256 + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + error: Optional[Exception] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/exceptions.md new file mode 100644 index 00000000..07f063f2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/exceptions.md @@ -0,0 +1,93 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/gas.md new file mode 100644 index 00000000..a1063c50 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/gas.md @@ -0,0 +1,213 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from ..fork_types import Address +from ..state import State, account_exists +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_SLOAD = Uint(50) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(10) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_EXTERNAL = Uint(20) +GAS_BALANCE = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_CALL = Uint(40) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + state: State, gas: Uint, to: Address, value: U256 +) -> MessageCallGas: + """ + Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`. + + Parameters + ---------- + state : + The current state. + gas : + The amount of gas provided to the message-call. + to: + The address of the recipient account. + value: + The amount of `ETH` that needs to be transferred. + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + create_gas_cost = Uint(0) if account_exists(state, to) else GAS_NEW_ACCOUNT + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + cost = GAS_CALL + gas + create_gas_cost + transfer_gas_cost + stipend = gas if value == 0 else GAS_CALL_STIPEND + gas + return MessageCallGas(cost, stipend) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/__init__.md new file mode 100644 index 00000000..443481c4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/__init__.md @@ -0,0 +1,334 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + SELFDESTRUCT = 0xFF + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/arithmetic.md new file mode 100644 index 00000000..1fc8d635 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/bitwise.md new file mode 100644 index 00000000..74ba4c50 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/bitwise.md @@ -0,0 +1,160 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/block.md new file mode 100644 index 00000000..d76a93ca --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/block.md @@ -0,0 +1,189 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/comparison.md new file mode 100644 index 00000000..1b14f9c2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/control_flow.md new file mode 100644 index 00000000..8673a8e9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/environment.md new file mode 100644 index 00000000..9c8a7c2a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/environment.md @@ -0,0 +1,381 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.utils.numeric import ceil32 + +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..gas import ( + GAS_BALANCE, + GAS_BASE, + GAS_COPY, + GAS_EXTERNAL, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_BALANCE) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_EXTERNAL) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/keccak.md new file mode 100644 index 00000000..cdef40a4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/log.md new file mode 100644 index 00000000..3ba1141d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/log.md @@ -0,0 +1,91 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 + +from ...blocks import Log +from .. import Evm +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/memory.md new file mode 100644 index 00000000..bba09640 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/stack.md new file mode 100644 index 00000000..9c9b10fc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/storage.md new file mode 100644 index 00000000..0c7c6563 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/storage.md @@ -0,0 +1,89 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" + +from ...state import get_storage, set_storage +from .. import Evm +from ..gas import ( + GAS_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + current_value = get_storage(evm.env.state, evm.message.current_target, key) + if new_value != 0 and current_value == 0: + gas_cost = GAS_STORAGE_SET + else: + gas_cost = GAS_STORAGE_UPDATE + + if new_value == 0 and current_value != 0: + evm.refund_counter += GAS_STORAGE_CLEAR_REFUND + + charge_gas(evm, gas_cost) + + # OPERATION + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/system.md new file mode 100644 index 00000000..75876df0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/instructions/system.md @@ -0,0 +1,381 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint + +from ...fork_types import Address +from ...state import ( + account_has_code_or_nonce, + get_account, + increment_nonce, + set_account_balance, +) +from ...utils.address import compute_contract_address, to_address +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..gas import ( + GAS_CREATE, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + create_message_gas = evm.gas_left + evm.gas_left = Uint(0) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + push(evm.stack, U256(0)) + evm.gas_left += create_message_gas + elif account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + else: + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push( + evm.stack, U256.from_be_bytes(child_evm.message.current_target) + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + evm.env.state, gas, to, value + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + evm.env.state, gas, to, value + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_ZERO + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/interpreter.md new file mode 100644 index 00000000..b4503178 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/interpreter.md @@ -0,0 +1,277 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + refund_counter = evm.refund_counter + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.frontier.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by two `CREATE` calls collide. + # * The first `CREATE` left empty code. + destroy_storage(env.state, message.current_target) + + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + except ExceptionalHalt: + evm.output = b"" + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.frontier.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=U256(0), + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + error=None, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/memory.md new file mode 100644 index 00000000..26468d3e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..0886a468 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/__init__.md @@ -0,0 +1,34 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..67019253 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..0bdc9476 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..bb9ce78a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/mapping.md @@ -0,0 +1,39 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .ecrecover import ecrecover +from .identity import identity +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..179a3a36 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..15cbf8ad --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/runtime.md new file mode 100644 index 00000000..21d5416b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/frontier/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/frontier/vm/stack.md new file mode 100644 index 00000000..92657776 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/frontier/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/frontier/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/genesis.md b/docs/revm-python-spec/revm-verif/spec/genesis.md new file mode 100644 index 00000000..1d720bf1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/genesis.md @@ -0,0 +1,209 @@ +# ๐Ÿ genesis.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/./genesis.py) + +```python +""" +Genesis Configuration +^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Functionalities and entities to obtain the genesis configurations for +different chains. +""" +import json +import pkgutil +from dataclasses import dataclass +from typing import Any, Dict, cast + +from ethereum import rlp +from ethereum.base_types import ( + U64, + U256, + Bytes, + Bytes8, + Bytes20, + Uint, + slotted_freezable, +) +from ethereum.utils.hexadecimal import ( + hex_to_bytes, + hex_to_bytes8, + hex_to_bytes32, + hex_to_u256, + hex_to_uint, +) + +Address = Bytes20 + + +@slotted_freezable +@dataclass +class GenesisConfiguration: + """ + Configuration for the first block of an Ethereum chain. + + Specifies the allocation of ether set out in the pre-sale, and some of + the fields of the genesis block. + """ + + chain_id: U64 + difficulty: Uint + extra_data: Bytes + gas_limit: Uint + nonce: Bytes8 + timestamp: U256 + initial_accounts: Dict[str, Dict] + + +def get_genesis_configuration(genesis_file: str) -> GenesisConfiguration: + """ + Obtain the genesis configuration from the given genesis json file. + + The genesis file should be present in the `assets` directory. + + Parameters + ---------- + genesis_file : + The json file which contains the parameters for the genesis block + and the pre-sale allocation data. + + Returns + ------- + configuration : `GenesisConfiguration` + The genesis configuration obtained from the json genesis file. + """ + genesis_str_data = cast( + bytes, pkgutil.get_data("ethereum", f"assets/{genesis_file}") + ).decode() + genesis_data = json.loads(genesis_str_data) + + return GenesisConfiguration( + chain_id=U64(genesis_data["config"]["chainId"]), + difficulty=hex_to_uint(genesis_data["difficulty"]), + extra_data=hex_to_bytes(genesis_data["extraData"]), + gas_limit=hex_to_uint(genesis_data["gasLimit"]), + nonce=hex_to_bytes8(genesis_data["nonce"]), + timestamp=hex_or_base_10_str_to_u256(genesis_data["timestamp"]), + initial_accounts=genesis_data["alloc"], + ) + + +def hex_or_base_10_str_to_u256(balance: str) -> U256: + """ + The genesis format can have balances and timestamps as either base 10 + numbers or 0x prefixed hex. This function supports both. + """ + if balance.startswith("0x"): + return hex_to_u256(balance) + else: + return U256(int(balance)) + + +def add_genesis_block( + hardfork: Any, chain: Any, genesis: GenesisConfiguration +) -> None: + """ + 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 https://github.com/ethereum/genesis_block_generator. + + 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 edgecases around precompiles being created or + cleared (by EIP 161). + + Parameters + ---------- + hardfork: + The module containing the initial hardfork + chain : + An empty `Blockchain` object. + genesis : + The genesis configuration to use. + """ + for address, account in genesis.initial_accounts.items(): + address = hardfork.utils.hexadecimal.hex_to_address(address) + hardfork.state.set_account( + chain.state, + address, + hardfork.fork_types.Account( + Uint(int(account.get("nonce", "0"))), + hex_or_base_10_str_to_u256(account.get("balance", 0)), + hex_to_bytes(account.get("code", "0x")), + ), + ) + for key, value in account.get("storage", {}).items(): + hardfork.state.set_storage( + chain.state, address, hex_to_bytes32(key), hex_to_uint(value) + ) + + fields = { + "parent_hash": hardfork.fork_types.Hash32(b"\0" * 32), + "ommers_hash": rlp.rlp_hash(()), + "coinbase": Address(b"\0" * 20), + "state_root": hardfork.state.state_root(chain.state), + "transactions_root": hardfork.trie.root( + hardfork.trie.Trie(False, None) + ), + "receipt_root": hardfork.trie.root(hardfork.trie.Trie(False, None)), + "bloom": hardfork.fork_types.Bloom(b"\0" * 256), + "difficulty": genesis.difficulty, + "number": Uint(0), + "gas_limit": genesis.gas_limit, + "gas_used": Uint(0), + "timestamp": genesis.timestamp, + "extra_data": genesis.extra_data, + "nonce": genesis.nonce, + } + + if hasattr(hardfork.blocks.Header, "mix_digest"): + fields["mix_digest"] = hardfork.fork_types.Hash32(b"\0" * 32) + else: + fields["prev_randao"] = hardfork.fork_types.Hash32(b"\0" * 32) + + if hasattr(hardfork.blocks.Header, "base_fee_per_gas"): + fields["base_fee_per_gas"] = Uint(10**9) + + genesis_header = hardfork.blocks.Header(**fields) + + genesis_block = hardfork.blocks.Block( + header=genesis_header, + transactions=(), + ommers=(), + ) + + chain.blocks.append(genesis_block) + chain.chain_id = genesis.chain_id +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/__init__.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/__init__.md new file mode 100644 index 00000000..03332aa5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/__init__.md @@ -0,0 +1,14 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/__init__.py) + +```python +""" +The Gray Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(15050000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/blocks.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/blocks.md new file mode 100644 index 00000000..799966ab --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/blocks.md @@ -0,0 +1,85 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import LegacyTransaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + base_fee_per_gas: Uint + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Union[Bytes, LegacyTransaction], ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/bloom.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/bloom.md new file mode 100644 index 00000000..5d66a5d3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/fork.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/fork.md new file mode 100644 index 00000000..142d8a3f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/fork.md @@ -0,0 +1,1259 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_ACCESS_LIST_ADDRESS_COST, + TX_ACCESS_LIST_STORAGE_KEY_COST, + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + AccessListTransaction, + FeeMarketTransaction, + LegacyTransaction, + Transaction, + decode_transaction, + encode_transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(2 * 10**18) +BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 +ELASTICITY_MULTIPLIER = 2 +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 +BOMB_DELAY_BLOCKS = 11400000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def calculate_base_fee_per_gas( + block_gas_limit: Uint, + parent_gas_limit: Uint, + parent_gas_used: Uint, + parent_base_fee_per_gas: Uint, +) -> Uint: + """ + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + """ + parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER + + ensure( + check_gas_limit(block_gas_limit, parent_gas_limit), + InvalidBlock, + ) + + if parent_gas_used == parent_gas_target: + expected_base_fee_per_gas = parent_base_fee_per_gas + elif parent_gas_used > parent_gas_target: + gas_used_delta = parent_gas_used - parent_gas_target + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = max( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, + 1, + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas + base_fee_per_gas_delta + ) + else: + gas_used_delta = parent_gas_target - parent_gas_used + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = ( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas - base_fee_per_gas_delta + ) + + return Uint(expected_base_fee_per_gas) + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.gas_used <= header.gas_limit, InvalidBlock) + + 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, + ) + + ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) + + parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + parent_has_ommers, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + header.base_fee_per_gas, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + base_fee_per_gas: Uint, + gas_available: Uint, + chain_id: U64, +) -> Tuple[Address, Uint]: + """ + 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. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + if isinstance(tx, FeeMarketTransaction): + ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock) + ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock) + + priority_fee_per_gas = min( + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas - base_fee_per_gas, + ) + effective_gas_price = priority_fee_per_gas + base_fee_per_gas + else: + ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock) + effective_gas_price = tx.gas_price + + return sender_address, effective_gas_price + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Union[Bytes, Receipt]: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + if isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(receipt) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(receipt) + else: + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + base_fee_per_gas: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Union[LegacyTransaction, Bytes], ...], + ommers: Tuple[Header, ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[ + Bytes, Optional[Union[Bytes, LegacyTransaction]] + ] = Trie(secured=False, default=None) + receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(map(decode_transaction, transactions)): + trie_set( + transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) + ) + + sender_address, effective_gas_price = check_transaction( + tx, base_fee_per_gas, gas_available, chain_id + ) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + base_fee_per_gas=base_fee_per_gas, + gas_price=effective_gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + chain_id=chain_id, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + + if isinstance(tx, FeeMarketTransaction): + max_gas_fee = tx.gas * tx.max_fee_per_gas + else: + max_gas_fee = tx.gas * tx.gas_price + + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + effective_gas_fee = tx.gas * env.gas_price + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + + sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + preaccessed_addresses = set() + preaccessed_storage_keys = set() + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for address, keys in tx.access_list: + preaccessed_addresses.add(address) + for key in keys: + preaccessed_storage_keys.add((address, key)) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + preaccessed_addresses=frozenset(preaccessed_addresses), + preaccessed_storage_keys=frozenset(preaccessed_storage_keys), + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 5, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price + + # For non-1559 transactions env.gas_price == tx.gas_price + priority_fee_per_gas = env.gas_price - env.base_fee_per_gas + transaction_fee = ( + tx.gas - output.gas_left - gas_refund + ) * priority_fee_per_gas + + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + access_list_cost = 0 + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for _address, keys in tx.access_list: + access_list_cost += TX_ACCESS_LIST_ADDRESS_COST + access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + + return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + r, s = tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + ensure( + v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock + ) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_2930(tx) + ) + elif isinstance(tx, FeeMarketTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_1559(tx) + ) + + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def signing_hash_2930(tx: AccessListTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x01" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x02" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, + parent_has_ommers: bool, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max( + (2 if parent_has_ommers else 1) + - int(block_timestamp - parent_timestamp) // 9, + -99, + ) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/fork_types.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/fork_types.md new file mode 100644 index 00000000..c5c3d120 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/state.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/state.md new file mode 100644 index 00000000..9702fb8e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/state.md @@ -0,0 +1,617 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + _created_accounts: Set[Address] = field(default_factory=set) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + del state._created_accounts + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def mark_account_created(state: State, address: Address) -> None: + """ + 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. + """ + state._created_accounts.add(address) + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) + + +def get_storage_original(state: State, address: Address, key: Bytes) -> U256: + """ + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + """ + # In the transaction where an account is created, its preexisting storage + # is ignored. + if address in state._created_accounts: + return U256(0) + + _, original_trie = state._snapshots[0] + original_account_trie = original_trie.get(address) + + if original_account_trie is None: + original_value = U256(0) + else: + original_value = trie_get(original_account_trie, key) + + assert isinstance(original_value, U256) + + return original_value +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/transactions.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/transactions.md new file mode 100644 index 00000000..72da56b3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/transactions.md @@ -0,0 +1,126 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from .. import rlp +from ..base_types import ( + U64, + U256, + Bytes, + Bytes0, + Bytes32, + Uint, + slotted_freezable, +) +from ..exceptions import InvalidBlock +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 +TX_ACCESS_LIST_ADDRESS_COST = 2400 +TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 + + +@slotted_freezable +@dataclass +class LegacyTransaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class AccessListTransaction: + """ + The transaction type added in EIP-2930 to support access lists. + """ + + chain_id: U64 + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class FeeMarketTransaction: + """ + The transaction type added in EIP-1559. + """ + + chain_id: U64 + nonce: U256 + max_priority_fee_per_gas: Uint + max_fee_per_gas: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +Transaction = Union[ + LegacyTransaction, AccessListTransaction, FeeMarketTransaction +] + + +def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: + """ + Encode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, LegacyTransaction): + return tx + elif isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(tx) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(tx) + else: + raise Exception(f"Unable to encode transaction of type {type(tx)}") + + +def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: + """ + Decode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, Bytes): + if tx[0] == 1: + return rlp.decode_to(AccessListTransaction, tx[1:]) + elif tx[0] == 2: + return rlp.decode_to(FeeMarketTransaction, tx[1:]) + else: + raise InvalidBlock + else: + return tx +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/trie.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/trie.md new file mode 100644 index 00000000..2d1e22d1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.arrow_glacier import trie as previous_trie +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import LegacyTransaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, LegacyTransaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Union[LegacyTransaction, Bytes]], + Optional[Union[Receipt, Bytes]], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (LegacyTransaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/__init__.md new file mode 100644 index 00000000..5bd40047 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/address.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/address.md new file mode 100644 index 00000000..d5b644ee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/address.md @@ -0,0 +1,97 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this gray_glacier version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.gray_glacier.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/hexadecimal.md new file mode 100644 index 00000000..ad0d0802 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/utils/hexadecimal.py) + +```python +""" +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. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/message.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/message.md new file mode 100644 index 00000000..ae2d7ebc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/utils/message.md @@ -0,0 +1,121 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/utils/message.py) + +```python +""" +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. +""" +from typing import FrozenSet, Optional, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Bytes32, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, + preaccessed_addresses: FrozenSet[Address] = frozenset(), + preaccessed_storage_keys: FrozenSet[ + Tuple[(Address, Bytes32)] + ] = frozenset(), +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.gray_glacier.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + accessed_addresses = set() + accessed_addresses.add(current_target) + accessed_addresses.add(caller) + accessed_addresses.update(PRE_COMPILED_CONTRACTS.keys()) + accessed_addresses.update(preaccessed_addresses) + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + accessed_addresses=accessed_addresses, + accessed_storage_keys=set(preaccessed_storage_keys), + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/__init__.md new file mode 100644 index 00000000..de882bdf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/__init__.md @@ -0,0 +1,152 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U64, U256, Bytes, Bytes0, Bytes32, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + base_fee_per_gas: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + chain_id: U64 + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: int + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + evm.accessed_addresses.update(child_evm.accessed_addresses) + evm.accessed_storage_keys.update(child_evm.accessed_storage_keys) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/exceptions.md new file mode 100644 index 00000000..d21f8d4a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/exceptions.md @@ -0,0 +1,138 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class InvalidParameter(ExceptionalHalt): + """ + Raised when invalid parameters are passed. + """ + + pass + + +class InvalidContractPrefix(ExceptionalHalt): + """ + Raised when the new contract code starts with 0xEF. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/gas.md new file mode 100644 index 00000000..f167b275 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/gas.md @@ -0,0 +1,245 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(4800) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_FAST_STEP = Uint(5) +GAS_BLAKE2_PER_ROUND = Uint(1) +GAS_COLD_SLOAD = Uint(2100) +GAS_COLD_ACCOUNT_ACCESS = Uint(2600) +GAS_WARM_ACCESS = Uint(100) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/__init__.md new file mode 100644 index 00000000..bf6837db --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/__init__.md @@ -0,0 +1,360 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + CHAINID = 0x46 + SELFBALANCE = 0x47 + BASEFEE = 0x48 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.CHAINID: block_instructions.chain_id, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SELFBALANCE: environment_instructions.self_balance, + Ops.BASEFEE: environment_instructions.base_fee, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/arithmetic.md new file mode 100644 index 00000000..c55bd863 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/bitwise.md new file mode 100644 index 00000000..32f68ec7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/block.md new file mode 100644 index 00000000..c65c05be --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/block.md @@ -0,0 +1,212 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def chain_id(evm: Evm) -> None: + """ + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.chain_id)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/comparison.md new file mode 100644 index 00000000..c58f8f38 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/control_flow.md new file mode 100644 index 00000000..08938c01 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/environment.md new file mode 100644 index 00000000..3f259d67 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/environment.md @@ -0,0 +1,543 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BASE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_COPY, + GAS_FAST_STEP, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + GAS_WARM_ACCESS, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) + else: + evm.accessed_addresses.add(address) + charge_gas( + evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 + + +def self_balance(evm: Evm) -> None: + """ + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_FAST_STEP) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, evm.message.current_target).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def base_fee(evm: Evm) -> None: + """ + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.base_fee_per_gas)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/keccak.md new file mode 100644 index 00000000..bc6451a1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/log.md new file mode 100644 index 00000000..034b3ffb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/memory.md new file mode 100644 index 00000000..0e88f192 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/stack.md new file mode 100644 index 00000000..791ce89b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/storage.md new file mode 100644 index 00000000..f43b526b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/storage.md @@ -0,0 +1,132 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.base_types import Uint +from ethereum.utils.ensure import ensure + +from ...state import get_storage, get_storage_original, set_storage +from .. import Evm +from ..exceptions import OutOfGasError, WriteInStaticContext +from ..gas import ( + GAS_CALL_STIPEND, + GAS_COLD_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + GAS_WARM_ACCESS, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + if (evm.message.current_target, key) in evm.accessed_storage_keys: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + charge_gas(evm, GAS_COLD_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + ensure(evm.gas_left > GAS_CALL_STIPEND, OutOfGasError) + + original_value = get_storage_original( + evm.env.state, evm.message.current_target, key + ) + current_value = get_storage(evm.env.state, evm.message.current_target, key) + + gas_cost = Uint(0) + + if (evm.message.current_target, key) not in evm.accessed_storage_keys: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + gas_cost += GAS_COLD_SLOAD + + if original_value == current_value and current_value != new_value: + if original_value == 0: + gas_cost += GAS_STORAGE_SET + else: + gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD + else: + gas_cost += GAS_WARM_ACCESS + + # Refund Counter Calculation + if current_value != new_value: + if original_value != 0 and current_value != 0 and new_value == 0: + # Storage is cleared for the first time in the transaction + evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND) + + if original_value != 0 and current_value == 0: + # Gas refund issued earlier to be reversed + evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND) + + if original_value == new_value: + # Storage slot being restored to its original value + if original_value == 0: + # Slot was originally empty and was SET earlier + evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + else: + # Slot was originally non-empty and was UPDATED earlier + evm.refund_counter += int( + GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS + ) + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/system.md new file mode 100644 index 00000000..e2015e2c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/instructions/system.md @@ -0,0 +1,669 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL_VALUE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_WARM_ACCESS, + GAS_ZERO, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + evm.accessed_addresses.add(contract_address) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + charge_gas( + evm, + GAS_CREATE + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + create_gas_cost = ( + Uint(0) + if is_account_alive(evm.env.state, to) or value == 0 + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if beneficiary not in evm.accessed_addresses: + evm.accessed_addresses.add(beneficiary) + gas_cost += GAS_COLD_ACCOUNT_ACCESS + + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + originator = evm.message.current_target + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/interpreter.md new file mode 100644 index 00000000..c2561555 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/interpreter.md @@ -0,0 +1,314 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + mark_account_created, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidContractPrefix, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = U256(evm.refund_counter) + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + # In the previously mentioned edge case the preexisting storage is ignored + # for gas refund purposes. In order to do this we must track created + # accounts. + mark_account_created(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + if len(contract_code) > 0: + ensure(contract_code[0] != 0xEF, InvalidContractPrefix) + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=0, + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + accessed_addresses=message.accessed_addresses, + accessed_storage_keys=message.accessed_storage_keys, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/memory.md new file mode 100644 index 00000000..ce96fdc5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..09e21425 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/__init__.md @@ -0,0 +1,44 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +BLAKE2F_ADDRESS = hex_to_address("0x09") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..83cc94de --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(150)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(6000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..2ff2241d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,50 @@ +# ๐Ÿ blake2f.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.py) + +```python +""" +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +""" +from ethereum.crypto.blake2 import Blake2b +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import GAS_BLAKE2_PER_ROUND, charge_gas +from ..exceptions import InvalidParameter + + +def blake2f(evm: Evm) -> None: + """ + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + ensure(len(data) == 213, InvalidParameter) + + blake2b = Blake2b() + rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) + + charge_gas(evm, GAS_BLAKE2_PER_ROUND * rounds) + + # OPERATION + ensure(f in [0, 1], InvalidParameter) + + evm.output = blake2b.compress(rounds, h, m, t_0, t_1, f) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..eec58176 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..09b8d74d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..2672ffb3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/mapping.md @@ -0,0 +1,52 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + BLAKE2F_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .blake2f import blake2f +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, + BLAKE2F_ADDRESS: blake2f, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..3af25ab2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/modexp.md @@ -0,0 +1,174 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = 3 + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = Uint.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + + charge_gas( + evm, + gas_cost(base_length, modulus_length, exp_length, exp_head), + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def complexity(base_length: U256, modulus_length: U256) -> Uint: + """ + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + """ + max_length = max(Uint(base_length), Uint(modulus_length)) + words = (max_length + 7) // 8 + return words**2 + + +def iterations(exponent_length: U256, exponent_head: Uint) -> Uint: + """ + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + """ + if exponent_length <= 32 and exponent_head == 0: + count = Uint(0) + elif exponent_length <= 32: + bit_length = Uint(exponent_head.bit_length()) + + if bit_length > 0: + bit_length -= 1 + + count = bit_length + else: + length_part = 8 * (Uint(exponent_length) - 32) + bits_part = Uint(exponent_head.bit_length()) + + if bits_part > 0: + bits_part -= 1 + + count = length_part + bits_part + + return max(count, Uint(1)) + + +def gas_cost( + base_length: U256, + modulus_length: U256, + exponent_length: U256, + exponent_head: Uint, +) -> Uint: + """ + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + """ + multiplication_complexity = complexity(base_length, modulus_length) + iteration_count = iterations(exponent_length, exponent_head) + cost = multiplication_complexity * iteration_count + cost //= GQUADDIVISOR + return max(Uint(200), cost) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..37382c98 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..0aa21ac9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/runtime.md new file mode 100644 index 00000000..578e51fe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/stack.md new file mode 100644 index 00000000..76a5ec7f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/gray_glacier/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/gray_glacier/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/__init__.md b/docs/revm-python-spec/revm-verif/spec/homestead/__init__.md new file mode 100644 index 00000000..2c6ccf63 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(1150000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/blocks.md b/docs/revm-python-spec/revm-verif/spec/homestead/blocks.md new file mode 100644 index 00000000..6e369b36 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import Transaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Transaction, ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + post_state: Root + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/bloom.md b/docs/revm-python-spec/revm-verif/spec/homestead/bloom.md new file mode 100644 index 00000000..0402217a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/fork.md b/docs/revm-python-spec/revm-verif/spec/homestead/fork.md new file mode 100644 index 00000000..527858d4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/fork.md @@ -0,0 +1,977 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Bytes32, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + Transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(5 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + post_state: Bytes32, + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Receipt: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + post_state=post_state, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Transaction, ...], + ommers: Tuple[Header, ...], +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[Bytes, Optional[Transaction]] = Trie( + secured=False, default=None + ) + receipts_trie: Trie[Bytes, Optional[Receipt]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(transactions): + trie_set(transactions_trie, rlp.encode(Uint(i)), tx) + + sender_address = check_transaction(tx, gas_available) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + traces=[], + ) + + gas_used, logs = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, state_root(state), (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + return total_gas_used, output.logs + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + return Uint(TX_BASE_COST + data_cost + create_cost) + + +def recover_sender(tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + v, r, s = tx.v, tx.r, tx.s + + # if v > 28: + # v = v - (chain_id*2+8) + + ensure(v == 27 or v == 28, InvalidBlock) + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + return Address(keccak256(public_key)[12:32]) + + +def signing_hash(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in the signature. + + The values that are used to compute the signing hash set the rules for a + transaction. For example, signing over the gas sets a limit for the + amount of money that is allowed to be pulled out of the sender's account. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max(1 - int(block_timestamp - parent_timestamp) // 10, -99) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = (int(block_number) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/fork_types.md b/docs/revm-python-spec/revm-verif/spec/homestead/fork_types.md new file mode 100644 index 00000000..4978f1c4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/state.md b/docs/revm-python-spec/revm-verif/spec/homestead/state.md new file mode 100644 index 00000000..afcaa114 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/state.md @@ -0,0 +1,479 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/transactions.md b/docs/revm-python-spec/revm-verif/spec/homestead/transactions.md new file mode 100644 index 00000000..3fdc6bec --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/transactions.md @@ -0,0 +1,39 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Union + +from ..base_types import U256, Bytes, Bytes0, Uint, slotted_freezable +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 68 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 + + +@slotted_freezable +@dataclass +class Transaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/trie.md b/docs/revm-python-spec/revm-verif/spec/homestead/trie.md new file mode 100644 index 00000000..094b0203 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.frontier import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import Transaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, Transaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Transaction], + Optional[Receipt], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (Transaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/homestead/utils/__init__.md new file mode 100644 index 00000000..fdb87191 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/utils/address.md b/docs/revm-python-spec/revm-verif/spec/homestead/utils/address.md new file mode 100644 index 00000000..791b86d6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/utils/address.md @@ -0,0 +1,67 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this homestead version of specification. +""" +from typing import Union + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.homestead.fork_types.Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/homestead/utils/hexadecimal.md new file mode 100644 index 00000000..51598e95 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Homestead +types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/utils/message.md b/docs/revm-python-spec/revm-verif/spec/homestead/utils/message.md new file mode 100644 index 00000000..a700503d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/utils/message.md @@ -0,0 +1,97 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/utils/message.py) + +```python +""" +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. +""" +from typing import Optional, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.homestead.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/__init__.md new file mode 100644 index 00000000..644681b3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/__init__.md @@ -0,0 +1,121 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: U256 + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + error: Optional[Exception] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/exceptions.md new file mode 100644 index 00000000..a811c5fd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/exceptions.md @@ -0,0 +1,93 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/gas.md new file mode 100644 index 00000000..9bb0cb83 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/gas.md @@ -0,0 +1,213 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from ..fork_types import Address +from ..state import State, account_exists +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_SLOAD = Uint(50) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(10) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_EXTERNAL = Uint(20) +GAS_BALANCE = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_CALL = Uint(40) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + state: State, gas: Uint, to: Address, value: U256 +) -> MessageCallGas: + """ + Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`. + + Parameters + ---------- + state : + The current state. + gas : + The amount of gas provided to the message-call. + to: + The address of the recipient account. + value: + The amount of `ETH` that needs to be transferred. + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + create_gas_cost = Uint(0) if account_exists(state, to) else GAS_NEW_ACCOUNT + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + cost = GAS_CALL + gas + create_gas_cost + transfer_gas_cost + stipend = gas if value == 0 else GAS_CALL_STIPEND + gas + return MessageCallGas(cost, stipend) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/__init__.md new file mode 100644 index 00000000..df15dbd2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/__init__.md @@ -0,0 +1,336 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + SELFDESTRUCT = 0xFF + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/arithmetic.md new file mode 100644 index 00000000..b41687bf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/bitwise.md new file mode 100644 index 00000000..63a76c93 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/bitwise.md @@ -0,0 +1,160 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/block.md new file mode 100644 index 00000000..b3c6e74b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/block.md @@ -0,0 +1,189 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/comparison.md new file mode 100644 index 00000000..f7fd23e8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/control_flow.md new file mode 100644 index 00000000..42acbe23 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/environment.md new file mode 100644 index 00000000..d494758a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/environment.md @@ -0,0 +1,381 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.utils.numeric import ceil32 + +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..gas import ( + GAS_BALANCE, + GAS_BASE, + GAS_COPY, + GAS_EXTERNAL, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_BALANCE) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_EXTERNAL) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/keccak.md new file mode 100644 index 00000000..61482863 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/log.md new file mode 100644 index 00000000..475ca1b0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/log.md @@ -0,0 +1,91 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 + +from ...blocks import Log +from .. import Evm +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/memory.md new file mode 100644 index 00000000..d62b1b21 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/stack.md new file mode 100644 index 00000000..17831128 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/storage.md new file mode 100644 index 00000000..a718b16d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/storage.md @@ -0,0 +1,89 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" + +from ...state import get_storage, set_storage +from .. import Evm +from ..gas import ( + GAS_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + current_value = get_storage(evm.env.state, evm.message.current_target, key) + if new_value != 0 and current_value == 0: + gas_cost = GAS_STORAGE_SET + else: + gas_cost = GAS_STORAGE_UPDATE + + if new_value == 0 and current_value != 0: + evm.refund_counter += GAS_STORAGE_CLEAR_REFUND + + charge_gas(evm, gas_cost) + + # OPERATION + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/system.md new file mode 100644 index 00000000..f284b0b6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/instructions/system.md @@ -0,0 +1,434 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint + +from ...fork_types import Address +from ...state import ( + account_has_code_or_nonce, + get_account, + increment_nonce, + set_account_balance, +) +from ...utils.address import compute_contract_address, to_address +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..gas import ( + GAS_CALL, + GAS_CREATE, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + create_message_gas = evm.gas_left + evm.gas_left = Uint(0) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + push(evm.stack, U256(0)) + evm.gas_left += create_message_gas + elif account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + else: + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push( + evm.stack, U256.from_be_bytes(child_evm.message.current_target) + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + evm.env.state, gas, to, value + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + evm.env.state, gas, to, value + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_ZERO + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + charge_gas(evm, GAS_CALL + gas + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + gas, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/interpreter.md new file mode 100644 index 00000000..aa0deed6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/interpreter.md @@ -0,0 +1,279 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + refund_counter = evm.refund_counter + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.homestead.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by two `CREATE` calls collide. + # * The first `CREATE` left empty code. + destroy_storage(env.state, message.current_target) + + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.homestead.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=U256(0), + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + error=None, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/memory.md new file mode 100644 index 00000000..65222469 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..934f97f5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/__init__.md @@ -0,0 +1,34 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..1c063163 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..2a91bb72 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..0a55e738 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/mapping.md @@ -0,0 +1,39 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .ecrecover import ecrecover +from .identity import identity +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..b5c85efe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..23c9df53 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/runtime.md new file mode 100644 index 00000000..faec8899 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/homestead/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/homestead/vm/stack.md new file mode 100644 index 00000000..d974a2ff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/homestead/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/homestead/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/__init__.md b/docs/revm-python-spec/revm-verif/spec/istanbul/__init__.md new file mode 100644 index 00000000..a304dac8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/__init__.md @@ -0,0 +1,15 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(9069000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/blocks.md b/docs/revm-python-spec/revm-verif/spec/istanbul/blocks.md new file mode 100644 index 00000000..cb90e291 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import Transaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Transaction, ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/bloom.md b/docs/revm-python-spec/revm-verif/spec/istanbul/bloom.md new file mode 100644 index 00000000..163a8f22 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/fork.md b/docs/revm-python-spec/revm-verif/spec/istanbul/fork.md new file mode 100644 index 00000000..2cd852dc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/fork.md @@ -0,0 +1,1037 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + Transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(2 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 +BOMB_DELAY_BLOCKS = 5000000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + parent_has_ommers, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, + chain_id: U64, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Receipt: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Transaction, ...], + ommers: Tuple[Header, ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[Bytes, Optional[Transaction]] = Trie( + secured=False, default=None + ) + receipts_trie: Trie[Bytes, Optional[Receipt]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(transactions): + trie_set(transactions_trie, rlp.encode(Uint(i)), tx) + + sender_address = check_transaction(tx, gas_available, chain_id) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + chain_id=chain_id, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + return Uint(TX_BASE_COST + data_cost + create_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + v, r, s = tx.v, tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if v == 27 or v == 28: + public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) + else: + ensure(v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: Transaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, + parent_has_ommers: bool, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max( + (2 if parent_has_ommers else 1) + - int(block_timestamp - parent_timestamp) // 9, + -99, + ) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/fork_types.md b/docs/revm-python-spec/revm-verif/spec/istanbul/fork_types.md new file mode 100644 index 00000000..b8dbf4ab --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/state.md b/docs/revm-python-spec/revm-verif/spec/istanbul/state.md new file mode 100644 index 00000000..ffa9bc83 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/state.md @@ -0,0 +1,617 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + _created_accounts: Set[Address] = field(default_factory=set) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + del state._created_accounts + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def mark_account_created(state: State, address: Address) -> None: + """ + 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. + """ + state._created_accounts.add(address) + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) + + +def get_storage_original(state: State, address: Address, key: Bytes) -> U256: + """ + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + """ + # In the transaction where an account is created, its preexisting storage + # is ignored. + if address in state._created_accounts: + return U256(0) + + _, original_trie = state._snapshots[0] + original_account_trie = original_trie.get(address) + + if original_account_trie is None: + original_value = U256(0) + else: + original_value = trie_get(original_account_trie, key) + + assert isinstance(original_value, U256) + + return original_value +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/transactions.md b/docs/revm-python-spec/revm-verif/spec/istanbul/transactions.md new file mode 100644 index 00000000..a92726b0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/transactions.md @@ -0,0 +1,39 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Union + +from ..base_types import U256, Bytes, Bytes0, Uint, slotted_freezable +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 + + +@slotted_freezable +@dataclass +class Transaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/trie.md b/docs/revm-python-spec/revm-verif/spec/istanbul/trie.md new file mode 100644 index 00000000..7163ab4a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.constantinople import trie as previous_trie +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import Transaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, Transaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Transaction], + Optional[Receipt], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (Transaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/istanbul/utils/__init__.md new file mode 100644 index 00000000..5dfeba32 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/utils/address.md b/docs/revm-python-spec/revm-verif/spec/istanbul/utils/address.md new file mode 100644 index 00000000..37ebbaad --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/utils/address.md @@ -0,0 +1,97 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this istanbul version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.istanbul.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/istanbul/utils/hexadecimal.md new file mode 100644 index 00000000..1f3e8885 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Istanbul types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/utils/message.md b/docs/revm-python-spec/revm-verif/spec/istanbul/utils/message.md new file mode 100644 index 00000000..7b8f9087 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/utils/message.md @@ -0,0 +1,103 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/utils/message.py) + +```python +""" +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. +""" +from typing import Optional, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.istanbul.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/__init__.md new file mode 100644 index 00000000..e79b2d46 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/__init__.md @@ -0,0 +1,145 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U64, U256, Bytes, Bytes0, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + chain_id: U64 + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: int + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/exceptions.md new file mode 100644 index 00000000..db16bd6a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/exceptions.md @@ -0,0 +1,130 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class InvalidParameter(ExceptionalHalt): + """ + Raised when invalid parameters are passed. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/gas.md new file mode 100644 index 00000000..9bce684e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/gas.md @@ -0,0 +1,248 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_SLOAD = Uint(800) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_EXTERNAL = Uint(700) +GAS_BALANCE = Uint(700) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_CALL = Uint(700) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_CODE_HASH = Uint(700) +GAS_FAST_STEP = Uint(5) +GAS_BLAKE2_PER_ROUND = Uint(1) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/__init__.md new file mode 100644 index 00000000..9e18192e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/__init__.md @@ -0,0 +1,358 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + CHAINID = 0x46 + SELFBALANCE = 0x47 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.CHAINID: block_instructions.chain_id, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SELFBALANCE: environment_instructions.self_balance, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/arithmetic.md new file mode 100644 index 00000000..ba22ed42 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/bitwise.md new file mode 100644 index 00000000..c9752f9c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/block.md new file mode 100644 index 00000000..79ba5f71 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/block.md @@ -0,0 +1,212 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def chain_id(evm: Evm) -> None: + """ + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.chain_id)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/comparison.md new file mode 100644 index 00000000..e5855e76 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/control_flow.md new file mode 100644 index 00000000..6dea2d53 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/environment.md new file mode 100644 index 00000000..16abe468 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/environment.md @@ -0,0 +1,502 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BALANCE, + GAS_BASE, + GAS_CODE_HASH, + GAS_COPY, + GAS_EXTERNAL, + GAS_FAST_STEP, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_BALANCE) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_EXTERNAL) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_CODE_HASH) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 + + +def self_balance(evm: Evm) -> None: + """ + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_FAST_STEP) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, evm.message.current_target).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/keccak.md new file mode 100644 index 00000000..a57d4e8b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/log.md new file mode 100644 index 00000000..572d8e4a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/memory.md new file mode 100644 index 00000000..80aad913 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/stack.md new file mode 100644 index 00000000..80c30c6c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/storage.md new file mode 100644 index 00000000..b781efda --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/storage.md @@ -0,0 +1,118 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.utils.ensure import ensure + +from ...state import get_storage, get_storage_original, set_storage +from .. import Evm +from ..exceptions import OutOfGasError, WriteInStaticContext +from ..gas import ( + GAS_CALL_STIPEND, + GAS_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + ensure(evm.gas_left > GAS_CALL_STIPEND, OutOfGasError) + + original_value = get_storage_original( + evm.env.state, evm.message.current_target, key + ) + current_value = get_storage(evm.env.state, evm.message.current_target, key) + + if original_value == current_value and current_value != new_value: + if original_value == 0: + gas_cost = GAS_STORAGE_SET + else: + gas_cost = GAS_STORAGE_UPDATE + else: + gas_cost = GAS_SLOAD + + # Refund Counter Calculation + if current_value != new_value: + if original_value != 0 and current_value != 0 and new_value == 0: + # Storage is cleared for the first time in the transaction + evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND) + + if original_value != 0 and current_value == 0: + # Gas refund issued earlier to be reversed + evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND) + + if original_value == new_value: + # Storage slot being restored to its original value + if original_value == 0: + # Slot was originally empty and was SET earlier + evm.refund_counter += int(GAS_STORAGE_SET - GAS_SLOAD) + else: + # Slot was originally non-empty and was UPDATED earlier + evm.refund_counter += int(GAS_STORAGE_UPDATE - GAS_SLOAD) + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/system.md new file mode 100644 index 00000000..92f29319 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/instructions/system.md @@ -0,0 +1,641 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL, + GAS_CALL_VALUE, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + charge_gas( + evm, + GAS_CREATE + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + create_gas_cost = ( + Uint(0) + if value == 0 or is_account_alive(evm.env.state, to) + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/interpreter.md new file mode 100644 index 00000000..c6b2e3ef --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/interpreter.md @@ -0,0 +1,312 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + mark_account_created, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = U256(evm.refund_counter) + # + REFUND_SELF_DESTRUCT * len( + # evm.accounts_to_delete + # ) + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.istanbul.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + # In the previously mentioned edge case the preexisting storage is ignored + # for gas refund purposes. In order to do this we must track created + # accounts. + mark_account_created(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.istanbul.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=0, + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/memory.md new file mode 100644 index 00000000..3ba7c691 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..c9c842f5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/__init__.md @@ -0,0 +1,44 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +BLAKE2F_ADDRESS = hex_to_address("0x09") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..b9aae708 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(150)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(6000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..503d6818 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,50 @@ +# ๐Ÿ blake2f.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/precompiled_contracts/blake2f.py) + +```python +""" +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +""" +from ethereum.crypto.blake2 import Blake2b +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import GAS_BLAKE2_PER_ROUND, charge_gas +from ..exceptions import InvalidParameter + + +def blake2f(evm: Evm) -> None: + """ + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + ensure(len(data) == 213, InvalidParameter) + + blake2b = Blake2b() + rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) + + charge_gas(evm, GAS_BLAKE2_PER_ROUND * rounds) + + # OPERATION + ensure(f in [0, 1], InvalidParameter) + + evm.output = blake2b.compress(rounds, h, m, t_0, t_1, f) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..600d24e3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..39600caf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..701dc569 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/mapping.md @@ -0,0 +1,52 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + BLAKE2F_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .blake2f import blake2f +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, + BLAKE2F_ADDRESS: blake2f, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..abc0fa1d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/modexp.md @@ -0,0 +1,92 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = Uint(20) + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = U256.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + if exp_length < 32: + adjusted_exp_length = Uint(max(0, exp_head.bit_length() - 1)) + else: + adjusted_exp_length = Uint( + 8 * (int(exp_length) - 32) + max(0, exp_head.bit_length() - 1) + ) + + charge_gas( + evm, + ( + get_mult_complexity(Uint(max(base_length, modulus_length))) + * max(adjusted_exp_length, Uint(1)) + ) + // GQUADDIVISOR, + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def get_mult_complexity(x: Uint) -> Uint: + """ + Estimate the complexity of performing Karatsuba multiplication. + """ + if x <= 64: + return x**2 + elif x <= 1024: + return x**2 // 4 + 96 * x - 3072 + else: + return x**2 // 16 + 480 * x - 199680 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..62050cb1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..c681e636 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/runtime.md new file mode 100644 index 00000000..f544b23a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/istanbul/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/stack.md new file mode 100644 index 00000000..b6857312 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/istanbul/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/istanbul/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/__init__.md b/docs/revm-python-spec/revm-verif/spec/london/__init__.md new file mode 100644 index 00000000..7a1ca487 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/__init__.md @@ -0,0 +1,14 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/__init__.py) + +```python +""" +The London fork overhauls the transaction fee market, changes gas refunds, +reserves a contract prefix for future use, and delays the difficulty bomb. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(12965000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/blocks.md b/docs/revm-python-spec/revm-verif/spec/london/blocks.md new file mode 100644 index 00000000..a0b04680 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/blocks.md @@ -0,0 +1,85 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import LegacyTransaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + base_fee_per_gas: Uint + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Union[Bytes, LegacyTransaction], ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/bloom.md b/docs/revm-python-spec/revm-verif/spec/london/bloom.md new file mode 100644 index 00000000..7782f804 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/fork.md b/docs/revm-python-spec/revm-verif/spec/london/fork.md new file mode 100644 index 00000000..afbd52e3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/fork.md @@ -0,0 +1,1267 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint +from . import FORK_CRITERIA, vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_ACCESS_LIST_ADDRESS_COST, + TX_ACCESS_LIST_STORAGE_KEY_COST, + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + AccessListTransaction, + FeeMarketTransaction, + LegacyTransaction, + Transaction, + decode_transaction, + encode_transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(2 * 10**18) +BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 +ELASTICITY_MULTIPLIER = 2 +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +INITIAL_BASE_FEE = 1000000000 +MAX_OMMER_DEPTH = 6 +BOMB_DELAY_BLOCKS = 9700000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def calculate_base_fee_per_gas( + block_gas_limit: Uint, + parent_gas_limit: Uint, + parent_gas_used: Uint, + parent_base_fee_per_gas: Uint, + is_fork_block: bool, +) -> Uint: + """ + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + is_fork_block : + Whether the block is the fork block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + """ + if is_fork_block: + return Uint(INITIAL_BASE_FEE) + parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER + + ensure( + check_gas_limit(block_gas_limit, parent_gas_limit), + InvalidBlock, + ) + + if parent_gas_used == parent_gas_target: + expected_base_fee_per_gas = parent_base_fee_per_gas + elif parent_gas_used > parent_gas_target: + gas_used_delta = parent_gas_used - parent_gas_target + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = max( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, + 1, + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas + base_fee_per_gas_delta + ) + else: + gas_used_delta = parent_gas_target - parent_gas_used + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = ( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas - base_fee_per_gas_delta + ) + + return Uint(expected_base_fee_per_gas) + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.gas_used <= header.gas_limit, InvalidBlock) + + is_fork_block = header.number == FORK_CRITERIA.block_number + 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, + is_fork_block, + ) + + ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) + + parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + parent_has_ommers, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + header.base_fee_per_gas, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + base_fee_per_gas: Uint, + gas_available: Uint, + chain_id: U64, +) -> Tuple[Address, Uint]: + """ + 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. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + if isinstance(tx, FeeMarketTransaction): + ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock) + ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock) + + priority_fee_per_gas = min( + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas - base_fee_per_gas, + ) + effective_gas_price = priority_fee_per_gas + base_fee_per_gas + else: + ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock) + effective_gas_price = tx.gas_price + + return sender_address, effective_gas_price + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Union[Bytes, Receipt]: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + if isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(receipt) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(receipt) + else: + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + base_fee_per_gas: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Union[LegacyTransaction, Bytes], ...], + ommers: Tuple[Header, ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[ + Bytes, Optional[Union[Bytes, LegacyTransaction]] + ] = Trie(secured=False, default=None) + receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(map(decode_transaction, transactions)): + trie_set( + transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) + ) + + sender_address, effective_gas_price = check_transaction( + tx, base_fee_per_gas, gas_available, chain_id + ) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + base_fee_per_gas=base_fee_per_gas, + gas_price=effective_gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + chain_id=chain_id, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + + if isinstance(tx, FeeMarketTransaction): + max_gas_fee = tx.gas * tx.max_fee_per_gas + else: + max_gas_fee = tx.gas * tx.gas_price + + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + effective_gas_fee = tx.gas * env.gas_price + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + + sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + preaccessed_addresses = set() + preaccessed_storage_keys = set() + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for address, keys in tx.access_list: + preaccessed_addresses.add(address) + for key in keys: + preaccessed_storage_keys.add((address, key)) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + preaccessed_addresses=frozenset(preaccessed_addresses), + preaccessed_storage_keys=frozenset(preaccessed_storage_keys), + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 5, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price + + # For non-1559 transactions env.gas_price == tx.gas_price + priority_fee_per_gas = env.gas_price - env.base_fee_per_gas + transaction_fee = ( + tx.gas - output.gas_left - gas_refund + ) * priority_fee_per_gas + + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + access_list_cost = 0 + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for _address, keys in tx.access_list: + access_list_cost += TX_ACCESS_LIST_ADDRESS_COST + access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + + return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + r, s = tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + ensure( + v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock + ) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_2930(tx) + ) + elif isinstance(tx, FeeMarketTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_1559(tx) + ) + + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def signing_hash_2930(tx: AccessListTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x01" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x02" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, + parent_has_ommers: bool, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max( + (2 if parent_has_ommers else 1) + - int(block_timestamp - parent_timestamp) // 9, + -99, + ) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/fork_types.md b/docs/revm-python-spec/revm-verif/spec/london/fork_types.md new file mode 100644 index 00000000..c38db853 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/state.md b/docs/revm-python-spec/revm-verif/spec/london/state.md new file mode 100644 index 00000000..0de17473 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/state.md @@ -0,0 +1,617 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + _created_accounts: Set[Address] = field(default_factory=set) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + del state._created_accounts + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def mark_account_created(state: State, address: Address) -> None: + """ + 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. + """ + state._created_accounts.add(address) + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) + + +def get_storage_original(state: State, address: Address, key: Bytes) -> U256: + """ + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + """ + # In the transaction where an account is created, its preexisting storage + # is ignored. + if address in state._created_accounts: + return U256(0) + + _, original_trie = state._snapshots[0] + original_account_trie = original_trie.get(address) + + if original_account_trie is None: + original_value = U256(0) + else: + original_value = trie_get(original_account_trie, key) + + assert isinstance(original_value, U256) + + return original_value +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/transactions.md b/docs/revm-python-spec/revm-verif/spec/london/transactions.md new file mode 100644 index 00000000..8c14a64c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/transactions.md @@ -0,0 +1,126 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from .. import rlp +from ..base_types import ( + U64, + U256, + Bytes, + Bytes0, + Bytes32, + Uint, + slotted_freezable, +) +from ..exceptions import InvalidBlock +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 +TX_ACCESS_LIST_ADDRESS_COST = 2400 +TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 + + +@slotted_freezable +@dataclass +class LegacyTransaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class AccessListTransaction: + """ + The transaction type added in EIP-2930 to support access lists. + """ + + chain_id: U64 + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class FeeMarketTransaction: + """ + The transaction type added in EIP-1559. + """ + + chain_id: U64 + nonce: U256 + max_priority_fee_per_gas: Uint + max_fee_per_gas: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +Transaction = Union[ + LegacyTransaction, AccessListTransaction, FeeMarketTransaction +] + + +def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: + """ + Encode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, LegacyTransaction): + return tx + elif isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(tx) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(tx) + else: + raise Exception(f"Unable to encode transaction of type {type(tx)}") + + +def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: + """ + Decode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, Bytes): + if tx[0] == 1: + return rlp.decode_to(AccessListTransaction, tx[1:]) + elif tx[0] == 2: + return rlp.decode_to(FeeMarketTransaction, tx[1:]) + else: + raise InvalidBlock + else: + return tx +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/trie.md b/docs/revm-python-spec/revm-verif/spec/london/trie.md new file mode 100644 index 00000000..8795d487 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.berlin import trie as previous_trie +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import LegacyTransaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, LegacyTransaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Union[LegacyTransaction, Bytes]], + Optional[Union[Receipt, Bytes]], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (LegacyTransaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/london/utils/__init__.md new file mode 100644 index 00000000..2c63f674 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/utils/address.md b/docs/revm-python-spec/revm-verif/spec/london/utils/address.md new file mode 100644 index 00000000..3bc8a936 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/utils/address.md @@ -0,0 +1,97 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this london version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.london.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/london/utils/hexadecimal.md new file mode 100644 index 00000000..f61ac262 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +London types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/utils/message.md b/docs/revm-python-spec/revm-verif/spec/london/utils/message.md new file mode 100644 index 00000000..2db89a3c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/utils/message.md @@ -0,0 +1,121 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/utils/message.py) + +```python +""" +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. +""" +from typing import FrozenSet, Optional, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Bytes32, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, + preaccessed_addresses: FrozenSet[Address] = frozenset(), + preaccessed_storage_keys: FrozenSet[ + Tuple[(Address, Bytes32)] + ] = frozenset(), +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.london.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + accessed_addresses = set() + accessed_addresses.add(current_target) + accessed_addresses.add(caller) + accessed_addresses.update(PRE_COMPILED_CONTRACTS.keys()) + accessed_addresses.update(preaccessed_addresses) + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + accessed_addresses=accessed_addresses, + accessed_storage_keys=set(preaccessed_storage_keys), + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/london/vm/__init__.md new file mode 100644 index 00000000..73bb8d90 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/__init__.md @@ -0,0 +1,152 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U64, U256, Bytes, Bytes0, Bytes32, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + base_fee_per_gas: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + chain_id: U64 + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: int + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + evm.accessed_addresses.update(child_evm.accessed_addresses) + evm.accessed_storage_keys.update(child_evm.accessed_storage_keys) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/london/vm/exceptions.md new file mode 100644 index 00000000..6d6154a2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/exceptions.md @@ -0,0 +1,138 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class InvalidParameter(ExceptionalHalt): + """ + Raised when invalid parameters are passed. + """ + + pass + + +class InvalidContractPrefix(ExceptionalHalt): + """ + Raised when the new contract code starts with 0xEF. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/london/vm/gas.md new file mode 100644 index 00000000..a8cdd848 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/gas.md @@ -0,0 +1,245 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(4800) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_FAST_STEP = Uint(5) +GAS_BLAKE2_PER_ROUND = Uint(1) +GAS_COLD_SLOAD = Uint(2100) +GAS_COLD_ACCOUNT_ACCESS = Uint(2600) +GAS_WARM_ACCESS = Uint(100) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/__init__.md new file mode 100644 index 00000000..9eb47452 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/__init__.md @@ -0,0 +1,360 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + CHAINID = 0x46 + SELFBALANCE = 0x47 + BASEFEE = 0x48 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.CHAINID: block_instructions.chain_id, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SELFBALANCE: environment_instructions.self_balance, + Ops.BASEFEE: environment_instructions.base_fee, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/arithmetic.md new file mode 100644 index 00000000..eda2b3d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/bitwise.md new file mode 100644 index 00000000..168555c8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/block.md new file mode 100644 index 00000000..424ce211 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/block.md @@ -0,0 +1,212 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def chain_id(evm: Evm) -> None: + """ + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.chain_id)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/comparison.md new file mode 100644 index 00000000..d880c0e8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/control_flow.md new file mode 100644 index 00000000..e82559ae --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/environment.md new file mode 100644 index 00000000..ba8ab118 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/environment.md @@ -0,0 +1,543 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BASE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_COPY, + GAS_FAST_STEP, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + GAS_WARM_ACCESS, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) + else: + evm.accessed_addresses.add(address) + charge_gas( + evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 + + +def self_balance(evm: Evm) -> None: + """ + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_FAST_STEP) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, evm.message.current_target).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def base_fee(evm: Evm) -> None: + """ + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.base_fee_per_gas)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/keccak.md new file mode 100644 index 00000000..229c9c3d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/log.md new file mode 100644 index 00000000..834c92d3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/memory.md new file mode 100644 index 00000000..ab7e382d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/stack.md new file mode 100644 index 00000000..0a48bbfa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/storage.md new file mode 100644 index 00000000..0122b6e9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/storage.md @@ -0,0 +1,132 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.base_types import Uint +from ethereum.utils.ensure import ensure + +from ...state import get_storage, get_storage_original, set_storage +from .. import Evm +from ..exceptions import OutOfGasError, WriteInStaticContext +from ..gas import ( + GAS_CALL_STIPEND, + GAS_COLD_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + GAS_WARM_ACCESS, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + if (evm.message.current_target, key) in evm.accessed_storage_keys: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + charge_gas(evm, GAS_COLD_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + ensure(evm.gas_left > GAS_CALL_STIPEND, OutOfGasError) + + original_value = get_storage_original( + evm.env.state, evm.message.current_target, key + ) + current_value = get_storage(evm.env.state, evm.message.current_target, key) + + gas_cost = Uint(0) + + if (evm.message.current_target, key) not in evm.accessed_storage_keys: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + gas_cost += GAS_COLD_SLOAD + + if original_value == current_value and current_value != new_value: + if original_value == 0: + gas_cost += GAS_STORAGE_SET + else: + gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD + else: + gas_cost += GAS_WARM_ACCESS + + # Refund Counter Calculation + if current_value != new_value: + if original_value != 0 and current_value != 0 and new_value == 0: + # Storage is cleared for the first time in the transaction + evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND) + + if original_value != 0 and current_value == 0: + # Gas refund issued earlier to be reversed + evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND) + + if original_value == new_value: + # Storage slot being restored to its original value + if original_value == 0: + # Slot was originally empty and was SET earlier + evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + else: + # Slot was originally non-empty and was UPDATED earlier + evm.refund_counter += int( + GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS + ) + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/system.md new file mode 100644 index 00000000..f1fbe8f9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/instructions/system.md @@ -0,0 +1,669 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL_VALUE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_WARM_ACCESS, + GAS_ZERO, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + evm.accessed_addresses.add(contract_address) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + charge_gas( + evm, + GAS_CREATE + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + create_gas_cost = ( + Uint(0) + if is_account_alive(evm.env.state, to) or value == 0 + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if beneficiary not in evm.accessed_addresses: + evm.accessed_addresses.add(beneficiary) + gas_cost += GAS_COLD_ACCOUNT_ACCESS + + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + originator = evm.message.current_target + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/london/vm/interpreter.md new file mode 100644 index 00000000..c2286c25 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/interpreter.md @@ -0,0 +1,314 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + mark_account_created, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidContractPrefix, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = U256(evm.refund_counter) + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + # In the previously mentioned edge case the preexisting storage is ignored + # for gas refund purposes. In order to do this we must track created + # accounts. + mark_account_created(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + if len(contract_code) > 0: + ensure(contract_code[0] != 0xEF, InvalidContractPrefix) + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=0, + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + accessed_addresses=message.accessed_addresses, + accessed_storage_keys=message.accessed_storage_keys, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/london/vm/memory.md new file mode 100644 index 00000000..06478972 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..a5e319d7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/__init__.md @@ -0,0 +1,44 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +BLAKE2F_ADDRESS = hex_to_address("0x09") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..9663bd94 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(150)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(6000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..6bd71014 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,50 @@ +# ๐Ÿ blake2f.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/precompiled_contracts/blake2f.py) + +```python +""" +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +""" +from ethereum.crypto.blake2 import Blake2b +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import GAS_BLAKE2_PER_ROUND, charge_gas +from ..exceptions import InvalidParameter + + +def blake2f(evm: Evm) -> None: + """ + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + ensure(len(data) == 213, InvalidParameter) + + blake2b = Blake2b() + rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) + + charge_gas(evm, GAS_BLAKE2_PER_ROUND * rounds) + + # OPERATION + ensure(f in [0, 1], InvalidParameter) + + evm.output = blake2b.compress(rounds, h, m, t_0, t_1, f) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..4829be23 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..1f55507f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..757a6da0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/mapping.md @@ -0,0 +1,52 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + BLAKE2F_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .blake2f import blake2f +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, + BLAKE2F_ADDRESS: blake2f, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..e16367e0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/modexp.md @@ -0,0 +1,174 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = 3 + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = Uint.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + + charge_gas( + evm, + gas_cost(base_length, modulus_length, exp_length, exp_head), + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def complexity(base_length: U256, modulus_length: U256) -> Uint: + """ + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + """ + max_length = max(Uint(base_length), Uint(modulus_length)) + words = (max_length + 7) // 8 + return words**2 + + +def iterations(exponent_length: U256, exponent_head: Uint) -> Uint: + """ + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + """ + if exponent_length <= 32 and exponent_head == 0: + count = Uint(0) + elif exponent_length <= 32: + bit_length = Uint(exponent_head.bit_length()) + + if bit_length > 0: + bit_length -= 1 + + count = bit_length + else: + length_part = 8 * (Uint(exponent_length) - 32) + bits_part = Uint(exponent_head.bit_length()) + + if bits_part > 0: + bits_part -= 1 + + count = length_part + bits_part + + return max(count, Uint(1)) + + +def gas_cost( + base_length: U256, + modulus_length: U256, + exponent_length: U256, + exponent_head: Uint, +) -> Uint: + """ + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + """ + multiplication_complexity = complexity(base_length, modulus_length) + iteration_count = iterations(exponent_length, exponent_head) + cost = multiplication_complexity * iteration_count + cost //= GQUADDIVISOR + return max(Uint(200), cost) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..6d2c6c47 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..3b4401eb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/london/vm/runtime.md new file mode 100644 index 00000000..49493472 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/london/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/london/vm/stack.md new file mode 100644 index 00000000..c8bc4234 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/london/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/london/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/__init__.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/__init__.md new file mode 100644 index 00000000..4173c1a8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/__init__.md @@ -0,0 +1,13 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/__init__.py) + +```python +""" +The Muir Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +""" +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(9200000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/blocks.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/blocks.md new file mode 100644 index 00000000..857ead9d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import Transaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Transaction, ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/bloom.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/bloom.md new file mode 100644 index 00000000..1dcf7898 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/fork.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/fork.md new file mode 100644 index 00000000..788c6fb1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/fork.md @@ -0,0 +1,1037 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + Transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(2 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 +BOMB_DELAY_BLOCKS = 9000000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + parent_has_ommers, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, + chain_id: U64, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Receipt: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Transaction, ...], + ommers: Tuple[Header, ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[Bytes, Optional[Transaction]] = Trie( + secured=False, default=None + ) + receipts_trie: Trie[Bytes, Optional[Receipt]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(transactions): + trie_set(transactions_trie, rlp.encode(Uint(i)), tx) + + sender_address = check_transaction(tx, gas_available, chain_id) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + chain_id=chain_id, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + return Uint(TX_BASE_COST + data_cost + create_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + v, r, s = tx.v, tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if v == 27 or v == 28: + public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) + else: + ensure(v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: Transaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, + parent_has_ommers: bool, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max( + (2 if parent_has_ommers else 1) + - int(block_timestamp - parent_timestamp) // 9, + -99, + ) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/fork_types.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/fork_types.md new file mode 100644 index 00000000..1c240dd2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/state.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/state.md new file mode 100644 index 00000000..796f1893 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/state.md @@ -0,0 +1,617 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + _created_accounts: Set[Address] = field(default_factory=set) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + del state._created_accounts + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def mark_account_created(state: State, address: Address) -> None: + """ + 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. + """ + state._created_accounts.add(address) + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) + + +def get_storage_original(state: State, address: Address, key: Bytes) -> U256: + """ + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + """ + # In the transaction where an account is created, its preexisting storage + # is ignored. + if address in state._created_accounts: + return U256(0) + + _, original_trie = state._snapshots[0] + original_account_trie = original_trie.get(address) + + if original_account_trie is None: + original_value = U256(0) + else: + original_value = trie_get(original_account_trie, key) + + assert isinstance(original_value, U256) + + return original_value +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/transactions.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/transactions.md new file mode 100644 index 00000000..397fc20a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/transactions.md @@ -0,0 +1,39 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Union + +from ..base_types import U256, Bytes, Bytes0, Uint, slotted_freezable +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 + + +@slotted_freezable +@dataclass +class Transaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/trie.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/trie.md new file mode 100644 index 00000000..b3868c2a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.istanbul import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import Transaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, Transaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Transaction], + Optional[Receipt], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (Transaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/__init__.md new file mode 100644 index 00000000..80d63b5c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/address.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/address.md new file mode 100644 index 00000000..0b0e6a91 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/address.md @@ -0,0 +1,97 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this muir_glacier version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.muir_glacier.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/hexadecimal.md new file mode 100644 index 00000000..b7c0ff23 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/utils/hexadecimal.py) + +```python +""" +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. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/message.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/message.md new file mode 100644 index 00000000..cfeb4f34 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/utils/message.md @@ -0,0 +1,103 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/utils/message.py) + +```python +""" +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. +""" +from typing import Optional, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.muir_glacier.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/__init__.md new file mode 100644 index 00000000..cb033531 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/__init__.md @@ -0,0 +1,145 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U64, U256, Bytes, Bytes0, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + chain_id: U64 + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: int + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/exceptions.md new file mode 100644 index 00000000..babeee93 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/exceptions.md @@ -0,0 +1,130 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class InvalidParameter(ExceptionalHalt): + """ + Raised when invalid parameters are passed. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/gas.md new file mode 100644 index 00000000..0cab92ff --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/gas.md @@ -0,0 +1,248 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_SLOAD = Uint(800) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_EXTERNAL = Uint(700) +GAS_BALANCE = Uint(700) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_CALL = Uint(700) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_CODE_HASH = Uint(700) +GAS_FAST_STEP = Uint(5) +GAS_BLAKE2_PER_ROUND = Uint(1) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/__init__.md new file mode 100644 index 00000000..436f2727 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/__init__.md @@ -0,0 +1,358 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + CHAINID = 0x46 + SELFBALANCE = 0x47 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.CHAINID: block_instructions.chain_id, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SELFBALANCE: environment_instructions.self_balance, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/arithmetic.md new file mode 100644 index 00000000..b90c64cc --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/bitwise.md new file mode 100644 index 00000000..9ae5fa90 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/block.md new file mode 100644 index 00000000..d59ff567 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/block.md @@ -0,0 +1,212 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def chain_id(evm: Evm) -> None: + """ + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.chain_id)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/comparison.md new file mode 100644 index 00000000..d825d4cb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/control_flow.md new file mode 100644 index 00000000..e9b30a21 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/environment.md new file mode 100644 index 00000000..609d8902 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/environment.md @@ -0,0 +1,502 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BALANCE, + GAS_BASE, + GAS_CODE_HASH, + GAS_COPY, + GAS_EXTERNAL, + GAS_FAST_STEP, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_BALANCE) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_EXTERNAL) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_CODE_HASH) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 + + +def self_balance(evm: Evm) -> None: + """ + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_FAST_STEP) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, evm.message.current_target).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/keccak.md new file mode 100644 index 00000000..59c92bc8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/log.md new file mode 100644 index 00000000..dde22edf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/memory.md new file mode 100644 index 00000000..ef5ac6f0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/stack.md new file mode 100644 index 00000000..df5d3d9f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/storage.md new file mode 100644 index 00000000..ba0ed136 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/storage.md @@ -0,0 +1,118 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.utils.ensure import ensure + +from ...state import get_storage, get_storage_original, set_storage +from .. import Evm +from ..exceptions import OutOfGasError, WriteInStaticContext +from ..gas import ( + GAS_CALL_STIPEND, + GAS_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + ensure(evm.gas_left > GAS_CALL_STIPEND, OutOfGasError) + + original_value = get_storage_original( + evm.env.state, evm.message.current_target, key + ) + current_value = get_storage(evm.env.state, evm.message.current_target, key) + + if original_value == current_value and current_value != new_value: + if original_value == 0: + gas_cost = GAS_STORAGE_SET + else: + gas_cost = GAS_STORAGE_UPDATE + else: + gas_cost = GAS_SLOAD + + # Refund Counter Calculation + if current_value != new_value: + if original_value != 0 and current_value != 0 and new_value == 0: + # Storage is cleared for the first time in the transaction + evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND) + + if original_value != 0 and current_value == 0: + # Gas refund issued earlier to be reversed + evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND) + + if original_value == new_value: + # Storage slot being restored to its original value + if original_value == 0: + # Slot was originally empty and was SET earlier + evm.refund_counter += int(GAS_STORAGE_SET - GAS_SLOAD) + else: + # Slot was originally non-empty and was UPDATED earlier + evm.refund_counter += int(GAS_STORAGE_UPDATE - GAS_SLOAD) + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/system.md new file mode 100644 index 00000000..09976fb5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/instructions/system.md @@ -0,0 +1,641 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL, + GAS_CALL_VALUE, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + charge_gas( + evm, + GAS_CREATE + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + create_gas_cost = ( + Uint(0) + if value == 0 or is_account_alive(evm.env.state, to) + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/interpreter.md new file mode 100644 index 00000000..822f3bb2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/interpreter.md @@ -0,0 +1,309 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + mark_account_created, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = U256(evm.refund_counter) + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.muir_glacier.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + # In the previously mentioned edge case the preexisting storage is ignored + # for gas refund purposes. In order to do this we must track created + # accounts. + mark_account_created(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.muir_glacier.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=0, + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/memory.md new file mode 100644 index 00000000..c0b295ae --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..1a91508f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/__init__.md @@ -0,0 +1,44 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +BLAKE2F_ADDRESS = hex_to_address("0x09") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..736588a7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(150)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(6000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..b284f08c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,50 @@ +# ๐Ÿ blake2f.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.py) + +```python +""" +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +""" +from ethereum.crypto.blake2 import Blake2b +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import GAS_BLAKE2_PER_ROUND, charge_gas +from ..exceptions import InvalidParameter + + +def blake2f(evm: Evm) -> None: + """ + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + ensure(len(data) == 213, InvalidParameter) + + blake2b = Blake2b() + rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) + + charge_gas(evm, GAS_BLAKE2_PER_ROUND * rounds) + + # OPERATION + ensure(f in [0, 1], InvalidParameter) + + evm.output = blake2b.compress(rounds, h, m, t_0, t_1, f) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..d7b11da9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..e4dc0205 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..440bd061 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/mapping.md @@ -0,0 +1,52 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + BLAKE2F_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .blake2f import blake2f +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, + BLAKE2F_ADDRESS: blake2f, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..65d18d33 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/modexp.md @@ -0,0 +1,92 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = Uint(20) + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = U256.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + if exp_length < 32: + adjusted_exp_length = Uint(max(0, exp_head.bit_length() - 1)) + else: + adjusted_exp_length = Uint( + 8 * (int(exp_length) - 32) + max(0, exp_head.bit_length() - 1) + ) + + charge_gas( + evm, + ( + get_mult_complexity(Uint(max(base_length, modulus_length))) + * max(adjusted_exp_length, Uint(1)) + ) + // GQUADDIVISOR, + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def get_mult_complexity(x: Uint) -> Uint: + """ + Estimate the complexity of performing Karatsuba multiplication. + """ + if x <= 64: + return x**2 + elif x <= 1024: + return x**2 // 4 + 96 * x - 3072 + else: + return x**2 // 16 + 480 * x - 199680 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..a94a258d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..71ebb3c1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/runtime.md new file mode 100644 index 00000000..83e29607 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/stack.md new file mode 100644 index 00000000..49eec5d7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/muir_glacier/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/muir_glacier/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/__init__.md b/docs/revm-python-spec/revm-verif/spec/paris/__init__.md new file mode 100644 index 00000000..4e412d66 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/__init__.md @@ -0,0 +1,22 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/__init__.py) + +```python +""" +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 +""" + +from ethereum.fork_criteria import ByBlockNumber + +# The actual trigger for the Paris hardfork was The Merge occurring when +# total difficulty (the sum of the all block difficulties) reached the +# Terminal Total Difficulty value (58750000000000000000000 on Mainnet). The +# Merge is now a historical event. +FORK_CRITERIA = ByBlockNumber(15537394) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/blocks.md b/docs/revm-python-spec/revm-verif/spec/paris/blocks.md new file mode 100644 index 00000000..a7a7237d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/blocks.md @@ -0,0 +1,85 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import LegacyTransaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + prev_randao: Bytes32 + nonce: Bytes8 + base_fee_per_gas: Uint + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Union[Bytes, LegacyTransaction], ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/bloom.md b/docs/revm-python-spec/revm-verif/spec/paris/bloom.md new file mode 100644 index 00000000..ab6d6a2e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/fork.md b/docs/revm-python-spec/revm-verif/spec/paris/fork.md new file mode 100644 index 00000000..34892dca --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/fork.md @@ -0,0 +1,977 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Tuple, Union + +from ethereum.base_types import Bytes0, Bytes32 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_ACCESS_LIST_ADDRESS_COST, + TX_ACCESS_LIST_STORAGE_KEY_COST, + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + AccessListTransaction, + FeeMarketTransaction, + LegacyTransaction, + Transaction, + decode_transaction, + encode_transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 +ELASTICITY_MULTIPLIER = 2 +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + ensure(block.ommers == (), InvalidBlock) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def calculate_base_fee_per_gas( + block_gas_limit: Uint, + parent_gas_limit: Uint, + parent_gas_used: Uint, + parent_base_fee_per_gas: Uint, +) -> Uint: + """ + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + """ + parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER + + ensure( + check_gas_limit(block_gas_limit, parent_gas_limit), + InvalidBlock, + ) + + if parent_gas_used == parent_gas_target: + expected_base_fee_per_gas = parent_base_fee_per_gas + elif parent_gas_used > parent_gas_target: + gas_used_delta = parent_gas_used - parent_gas_target + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = max( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, + 1, + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas + base_fee_per_gas_delta + ) + else: + gas_used_delta = parent_gas_target - parent_gas_used + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = ( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas - base_fee_per_gas_delta + ) + + return Uint(expected_base_fee_per_gas) + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.gas_used <= header.gas_limit, InvalidBlock) + + 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, + ) + + ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) + + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + ensure(header.difficulty == 0, InvalidBlock) + ensure(header.nonce == b"\x00\x00\x00\x00\x00\x00\x00\x00", InvalidBlock) + ensure(header.ommers_hash == EMPTY_OMMER_HASH, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + +def check_transaction( + tx: Transaction, + base_fee_per_gas: Uint, + gas_available: Uint, + chain_id: U64, +) -> Tuple[Address, Uint]: + """ + 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. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + if isinstance(tx, FeeMarketTransaction): + ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock) + ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock) + + priority_fee_per_gas = min( + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas - base_fee_per_gas, + ) + effective_gas_price = priority_fee_per_gas + base_fee_per_gas + else: + ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock) + effective_gas_price = tx.gas_price + + return sender_address, effective_gas_price + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Union[Bytes, Receipt]: + """ + 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. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + if isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(receipt) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(receipt) + else: + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + base_fee_per_gas: Uint, + block_gas_limit: Uint, + block_time: U256, + prev_randao: Bytes32, + transactions: Tuple[Union[LegacyTransaction, Bytes], ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + prev_randao : + The previous randao from the beacon chain. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[ + Bytes, Optional[Union[Bytes, LegacyTransaction]] + ] = Trie(secured=False, default=None) + receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(map(decode_transaction, transactions)): + trie_set( + transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) + ) + + sender_address, effective_gas_price = check_transaction( + tx, base_fee_per_gas, gas_available, chain_id + ) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + base_fee_per_gas=base_fee_per_gas, + gas_price=effective_gas_price, + time=block_time, + prev_randao=prev_randao, + state=state, + chain_id=chain_id, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + + if isinstance(tx, FeeMarketTransaction): + max_gas_fee = tx.gas * tx.max_fee_per_gas + else: + max_gas_fee = tx.gas * tx.gas_price + + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + effective_gas_fee = tx.gas * env.gas_price + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + + sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + preaccessed_addresses = set() + preaccessed_storage_keys = set() + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for address, keys in tx.access_list: + preaccessed_addresses.add(address) + for key in keys: + preaccessed_storage_keys.add((address, key)) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + preaccessed_addresses=frozenset(preaccessed_addresses), + preaccessed_storage_keys=frozenset(preaccessed_storage_keys), + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 5, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price + + # For non-1559 transactions env.gas_price == tx.gas_price + priority_fee_per_gas = env.gas_price - env.base_fee_per_gas + transaction_fee = ( + tx.gas - output.gas_left - gas_refund + ) * priority_fee_per_gas + + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + access_list_cost = 0 + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for _address, keys in tx.access_list: + access_list_cost += TX_ACCESS_LIST_ADDRESS_COST + access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + + return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + r, s = tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + ensure( + v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock + ) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_2930(tx) + ) + elif isinstance(tx, FeeMarketTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_1559(tx) + ) + + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def signing_hash_2930(tx: AccessListTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x01" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x02" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/fork_types.md b/docs/revm-python-spec/revm-verif/spec/paris/fork_types.md new file mode 100644 index 00000000..9f27a74e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/state.md b/docs/revm-python-spec/revm-verif/spec/paris/state.md new file mode 100644 index 00000000..bab69340 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/state.md @@ -0,0 +1,597 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + _created_accounts: Set[Address] = field(default_factory=set) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + del state._created_accounts + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def mark_account_created(state: State, address: Address) -> None: + """ + 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. + """ + state._created_accounts.add(address) + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def get_storage_original(state: State, address: Address, key: Bytes) -> U256: + """ + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + """ + # In the transaction where an account is created, its preexisting storage + # is ignored. + if address in state._created_accounts: + return U256(0) + + _, original_trie = state._snapshots[0] + original_account_trie = original_trie.get(address) + + if original_account_trie is None: + original_value = U256(0) + else: + original_value = trie_get(original_account_trie, key) + + assert isinstance(original_value, U256) + + return original_value +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/transactions.md b/docs/revm-python-spec/revm-verif/spec/paris/transactions.md new file mode 100644 index 00000000..069d1692 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/transactions.md @@ -0,0 +1,126 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from .. import rlp +from ..base_types import ( + U64, + U256, + Bytes, + Bytes0, + Bytes32, + Uint, + slotted_freezable, +) +from ..exceptions import InvalidBlock +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 +TX_ACCESS_LIST_ADDRESS_COST = 2400 +TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 + + +@slotted_freezable +@dataclass +class LegacyTransaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class AccessListTransaction: + """ + The transaction type added in EIP-2930 to support access lists. + """ + + chain_id: U64 + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class FeeMarketTransaction: + """ + The transaction type added in EIP-1559. + """ + + chain_id: U64 + nonce: U256 + max_priority_fee_per_gas: Uint + max_fee_per_gas: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +Transaction = Union[ + LegacyTransaction, AccessListTransaction, FeeMarketTransaction +] + + +def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: + """ + Encode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, LegacyTransaction): + return tx + elif isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(tx) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(tx) + else: + raise Exception(f"Unable to encode transaction of type {type(tx)}") + + +def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: + """ + Decode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, Bytes): + if tx[0] == 1: + return rlp.decode_to(AccessListTransaction, tx[1:]) + elif tx[0] == 2: + return rlp.decode_to(FeeMarketTransaction, tx[1:]) + else: + raise InvalidBlock + else: + return tx +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/trie.md b/docs/revm-python-spec/revm-verif/spec/paris/trie.md new file mode 100644 index 00000000..28e6942b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.gray_glacier import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import LegacyTransaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, LegacyTransaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Union[LegacyTransaction, Bytes]], + Optional[Union[Receipt, Bytes]], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (LegacyTransaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/paris/utils/__init__.md new file mode 100644 index 00000000..01bd5672 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/utils/address.md b/docs/revm-python-spec/revm-verif/spec/paris/utils/address.md new file mode 100644 index 00000000..590f654e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/utils/address.md @@ -0,0 +1,97 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this paris version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.paris.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/paris/utils/hexadecimal.md new file mode 100644 index 00000000..992ce9c3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Paris types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/utils/message.md b/docs/revm-python-spec/revm-verif/spec/paris/utils/message.md new file mode 100644 index 00000000..a753cf34 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/utils/message.md @@ -0,0 +1,121 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/utils/message.py) + +```python +""" +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. +""" +from typing import FrozenSet, Optional, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Bytes32, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, + preaccessed_addresses: FrozenSet[Address] = frozenset(), + preaccessed_storage_keys: FrozenSet[ + Tuple[(Address, Bytes32)] + ] = frozenset(), +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.paris.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + accessed_addresses = set() + accessed_addresses.add(current_target) + accessed_addresses.add(caller) + accessed_addresses.update(PRE_COMPILED_CONTRACTS.keys()) + accessed_addresses.update(preaccessed_addresses) + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + accessed_addresses=accessed_addresses, + accessed_storage_keys=set(preaccessed_storage_keys), + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/__init__.md new file mode 100644 index 00000000..b7b0b6d7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/__init__.md @@ -0,0 +1,152 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U64, U256, Bytes, Bytes0, Bytes32, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + base_fee_per_gas: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + prev_randao: Bytes32 + state: State + chain_id: U64 + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: int + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + evm.accessed_addresses.update(child_evm.accessed_addresses) + evm.accessed_storage_keys.update(child_evm.accessed_storage_keys) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/exceptions.md new file mode 100644 index 00000000..10433dfa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/exceptions.md @@ -0,0 +1,138 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class InvalidParameter(ExceptionalHalt): + """ + Raised when invalid parameters are passed. + """ + + pass + + +class InvalidContractPrefix(ExceptionalHalt): + """ + Raised when the new contract code starts with 0xEF. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/gas.md new file mode 100644 index 00000000..1dc6685c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/gas.md @@ -0,0 +1,245 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(4800) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_FAST_STEP = Uint(5) +GAS_BLAKE2_PER_ROUND = Uint(1) +GAS_COLD_SLOAD = Uint(2100) +GAS_COLD_ACCOUNT_ACCESS = Uint(2600) +GAS_WARM_ACCESS = Uint(100) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/__init__.md new file mode 100644 index 00000000..9e351efe --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/__init__.md @@ -0,0 +1,360 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + PREVRANDAO = 0x44 + GASLIMIT = 0x45 + CHAINID = 0x46 + SELFBALANCE = 0x47 + BASEFEE = 0x48 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.PREVRANDAO: block_instructions.prev_randao, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.CHAINID: block_instructions.chain_id, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SELFBALANCE: environment_instructions.self_balance, + Ops.BASEFEE: environment_instructions.base_fee, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/arithmetic.md new file mode 100644 index 00000000..c571e295 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/bitwise.md new file mode 100644 index 00000000..f88ab374 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/block.md new file mode 100644 index 00000000..95c86d3f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/block.md @@ -0,0 +1,254 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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`. + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def prev_randao(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.prev_randao)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def chain_id(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.chain_id)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/comparison.md new file mode 100644 index 00000000..16f3a4a0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/control_flow.md new file mode 100644 index 00000000..d35290aa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/environment.md new file mode 100644 index 00000000..9b040e40 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/environment.md @@ -0,0 +1,543 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BASE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_COPY, + GAS_FAST_STEP, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + GAS_WARM_ACCESS, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) + else: + evm.accessed_addresses.add(address) + charge_gas( + evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 + + +def self_balance(evm: Evm) -> None: + """ + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_FAST_STEP) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, evm.message.current_target).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def base_fee(evm: Evm) -> None: + """ + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.base_fee_per_gas)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/keccak.md new file mode 100644 index 00000000..3e21c33c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/log.md new file mode 100644 index 00000000..c7ce08c0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/memory.md new file mode 100644 index 00000000..19ab48f0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/stack.md new file mode 100644 index 00000000..0a5aa330 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/storage.md new file mode 100644 index 00000000..505056b5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/storage.md @@ -0,0 +1,132 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.base_types import Uint +from ethereum.utils.ensure import ensure + +from ...state import get_storage, get_storage_original, set_storage +from .. import Evm +from ..exceptions import OutOfGasError, WriteInStaticContext +from ..gas import ( + GAS_CALL_STIPEND, + GAS_COLD_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + GAS_WARM_ACCESS, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + if (evm.message.current_target, key) in evm.accessed_storage_keys: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + charge_gas(evm, GAS_COLD_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + ensure(evm.gas_left > GAS_CALL_STIPEND, OutOfGasError) + + original_value = get_storage_original( + evm.env.state, evm.message.current_target, key + ) + current_value = get_storage(evm.env.state, evm.message.current_target, key) + + gas_cost = Uint(0) + + if (evm.message.current_target, key) not in evm.accessed_storage_keys: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + gas_cost += GAS_COLD_SLOAD + + if original_value == current_value and current_value != new_value: + if original_value == 0: + gas_cost += GAS_STORAGE_SET + else: + gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD + else: + gas_cost += GAS_WARM_ACCESS + + # Refund Counter Calculation + if current_value != new_value: + if original_value != 0 and current_value != 0 and new_value == 0: + # Storage is cleared for the first time in the transaction + evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND) + + if original_value != 0 and current_value == 0: + # Gas refund issued earlier to be reversed + evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND) + + if original_value == new_value: + # Storage slot being restored to its original value + if original_value == 0: + # Slot was originally empty and was SET earlier + evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + else: + # Slot was originally non-empty and was UPDATED earlier + evm.refund_counter += int( + GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS + ) + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/system.md new file mode 100644 index 00000000..c37269f5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/instructions/system.md @@ -0,0 +1,669 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL_VALUE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_WARM_ACCESS, + GAS_ZERO, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + evm.accessed_addresses.add(contract_address) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + charge_gas( + evm, + GAS_CREATE + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, endowment, contract_address, memory_start_position, memory_size + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + create_gas_cost = ( + Uint(0) + if is_account_alive(evm.env.state, to) or value == 0 + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if beneficiary not in evm.accessed_addresses: + evm.accessed_addresses.add(beneficiary) + gas_cost += GAS_COLD_ACCOUNT_ACCESS + + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + originator = evm.message.current_target + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/interpreter.md new file mode 100644 index 00000000..1e23ec7a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/interpreter.md @@ -0,0 +1,314 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + mark_account_created, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidContractPrefix, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Union[Tuple[()], Tuple[Log, ...]] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = U256(evm.refund_counter) + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.paris.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + # In the previously mentioned edge case the preexisting storage is ignored + # for gas refund purposes. In order to do this we must track created + # accounts. + mark_account_created(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + if len(contract_code) > 0: + ensure(contract_code[0] != 0xEF, InvalidContractPrefix) + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.paris.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=0, + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + accessed_addresses=message.accessed_addresses, + accessed_storage_keys=message.accessed_storage_keys, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/memory.md new file mode 100644 index 00000000..2b89a614 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..87a57d27 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/__init__.md @@ -0,0 +1,44 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +BLAKE2F_ADDRESS = hex_to_address("0x09") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..5822b93e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(150)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(6000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..829b7f2c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,50 @@ +# ๐Ÿ blake2f.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/precompiled_contracts/blake2f.py) + +```python +""" +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +""" +from ethereum.crypto.blake2 import Blake2b +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import GAS_BLAKE2_PER_ROUND, charge_gas +from ..exceptions import InvalidParameter + + +def blake2f(evm: Evm) -> None: + """ + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + ensure(len(data) == 213, InvalidParameter) + + blake2b = Blake2b() + rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) + + charge_gas(evm, GAS_BLAKE2_PER_ROUND * rounds) + + # OPERATION + ensure(f in [0, 1], InvalidParameter) + + evm.output = blake2b.compress(rounds, h, m, t_0, t_1, f) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..a838d9b7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..20fd3fe1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..4d3f338c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/mapping.md @@ -0,0 +1,52 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + BLAKE2F_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .blake2f import blake2f +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, + BLAKE2F_ADDRESS: blake2f, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..90ade2ee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/modexp.md @@ -0,0 +1,174 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = 3 + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = Uint.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + + charge_gas( + evm, + gas_cost(base_length, modulus_length, exp_length, exp_head), + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def complexity(base_length: U256, modulus_length: U256) -> Uint: + """ + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + """ + max_length = max(Uint(base_length), Uint(modulus_length)) + words = (max_length + 7) // 8 + return words**2 + + +def iterations(exponent_length: U256, exponent_head: Uint) -> Uint: + """ + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + """ + if exponent_length <= 32 and exponent_head == 0: + count = Uint(0) + elif exponent_length <= 32: + bit_length = Uint(exponent_head.bit_length()) + + if bit_length > 0: + bit_length -= 1 + + count = bit_length + else: + length_part = 8 * (Uint(exponent_length) - 32) + bits_part = Uint(exponent_head.bit_length()) + + if bits_part > 0: + bits_part -= 1 + + count = length_part + bits_part + + return max(count, Uint(1)) + + +def gas_cost( + base_length: U256, + modulus_length: U256, + exponent_length: U256, + exponent_head: Uint, +) -> Uint: + """ + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + """ + multiplication_complexity = complexity(base_length, modulus_length) + iteration_count = iterations(exponent_length, exponent_head) + cost = multiplication_complexity * iteration_count + cost //= GQUADDIVISOR + return max(Uint(200), cost) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..e24af54a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..f6787bb3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/runtime.md new file mode 100644 index 00000000..c177bbb6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/paris/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/paris/vm/stack.md new file mode 100644 index 00000000..860f110a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/paris/vm/stack.md @@ -0,0 +1,83 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/paris/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def get_length(evm: List[U256]) -> int: + """ + Returns the length of the stack. + + Parameters + ---------- + evm : + EVM stack. + + Returns + ------- + length : `int` + Length of the stack. + + """ + return len(evm) + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/rlp.md b/docs/revm-python-spec/revm-verif/spec/rlp.md new file mode 100644 index 00000000..43a040d8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/rlp.md @@ -0,0 +1,516 @@ +# ๐Ÿ rlp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/./rlp.py) + +```python +""" +.. _rlp: + +Recursive Length Prefix (RLP) Encoding +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Defines the serialization and deserialization format used throughout Ethereum. +""" + +from dataclasses import astuple, fields, is_dataclass +from typing import Any, List, Sequence, Tuple, Type, TypeVar, Union, cast + +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import RLPDecodingError, RLPEncodingError +from ethereum.utils.ensure import ensure + +from .base_types import Bytes, Bytes0, Bytes20, FixedBytes, FixedUint, Uint + +RLP = Any + + +# +# RLP Encode +# + + +def encode(raw_data: RLP) -> Bytes: + """ + Encodes `raw_data` into a sequence of bytes using RLP. + + Parameters + ---------- + raw_data : + A `Bytes`, `Uint`, `Uint256` or sequence of `RLP` encodable + objects. + + Returns + ------- + encoded : `ethereum.base_types.Bytes` + The RLP encoded bytes representing `raw_data`. + """ + if isinstance(raw_data, (bytearray, bytes)): + return encode_bytes(raw_data) + elif isinstance(raw_data, (Uint, FixedUint)): + return encode(raw_data.to_be_bytes()) + elif isinstance(raw_data, str): + return encode_bytes(raw_data.encode()) + elif isinstance(raw_data, bool): + if raw_data: + return encode_bytes(b"\x01") + else: + return encode_bytes(b"") + elif isinstance(raw_data, Sequence): + return encode_sequence(raw_data) + elif is_dataclass(raw_data): + return encode(astuple(raw_data)) + else: + raise RLPEncodingError( + "RLP Encoding of type {} is not supported".format(type(raw_data)) + ) + + +def encode_bytes(raw_bytes: Bytes) -> Bytes: + """ + Encodes `raw_bytes`, a sequence of bytes, using RLP. + + Parameters + ---------- + raw_bytes : + Bytes to encode with RLP. + + Returns + ------- + encoded : `ethereum.base_types.Bytes` + The RLP encoded bytes representing `raw_bytes`. + """ + len_raw_data = Uint(len(raw_bytes)) + + if len_raw_data == 1 and raw_bytes[0] < 0x80: + return raw_bytes + elif len_raw_data < 0x38: + return bytes([0x80 + len_raw_data]) + raw_bytes + else: + # length of raw data represented as big endian bytes + len_raw_data_as_be = len_raw_data.to_be_bytes() + return ( + bytes([0xB7 + len(len_raw_data_as_be)]) + + len_raw_data_as_be + + raw_bytes + ) + + +def encode_sequence(raw_sequence: Sequence[RLP]) -> Bytes: + """ + Encodes a list of RLP encodable objects (`raw_sequence`) using RLP. + + Parameters + ---------- + raw_sequence : + Sequence of RLP encodable objects. + + Returns + ------- + encoded : `ethereum.base_types.Bytes` + The RLP encoded bytes representing `raw_sequence`. + """ + joined_encodings = get_joined_encodings(raw_sequence) + len_joined_encodings = Uint(len(joined_encodings)) + + if len_joined_encodings < 0x38: + return Bytes([0xC0 + len_joined_encodings]) + joined_encodings + else: + len_joined_encodings_as_be = len_joined_encodings.to_be_bytes() + return ( + Bytes([0xF7 + len(len_joined_encodings_as_be)]) + + len_joined_encodings_as_be + + joined_encodings + ) + + +def get_joined_encodings(raw_sequence: Sequence[RLP]) -> Bytes: + """ + Obtain concatenation of rlp encoding for each item in the sequence + raw_sequence. + + Parameters + ---------- + raw_sequence : + Sequence to encode with RLP. + + Returns + ------- + joined_encodings : `ethereum.base_types.Bytes` + The concatenated RLP encoded bytes for each item in sequence + raw_sequence. + """ + return b"".join(encode(item) for item in raw_sequence) + + +# +# RLP Decode +# + + +def decode(encoded_data: Bytes) -> RLP: + """ + 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`. + """ + # Raising error as there can never be empty encoded data for any + # given raw data (including empty raw data) + # RLP Encoding(b'') -> [0x80] # noqa: SC100 + # RLP Encoding([]) -> [0xc0] # noqa: SC100 + ensure( + len(encoded_data) > 0, + RLPDecodingError("Cannot decode empty bytestring"), + ) + + if encoded_data[0] <= 0xBF: + # This means that the raw data is of type bytes + return decode_to_bytes(encoded_data) + else: + # This means that the raw data is of type sequence + return decode_to_sequence(encoded_data) + + +T = TypeVar("T") + + +def decode_to(cls: Type[T], encoded_data: Bytes) -> T: + """ + 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[T]` + The type to decode to. + encoded_data : + A sequence of bytes, in RLP form. + + Returns + ------- + decoded_data : `T` + Object decoded from `encoded_data`. + """ + return _decode_to(cls, decode(encoded_data)) + + +def _decode_to(cls: Type[T], raw_rlp: RLP) -> T: + """ + Decode the rlp structure in `encoded_data` to an object of type `cls`. + `cls` can be a `Bytes` subclass, a dataclass, `Uint`, `U256`, + `Tuple[cls, ...]`, `Tuple[cls1, cls2]` or `Union[Bytes, cls]`. + + Parameters + ---------- + cls: `Type[T]` + The type to decode to. + raw_rlp : + A decoded rlp structure. + + Returns + ------- + decoded_data : `T` + Object decoded from `encoded_data`. + """ + if isinstance(cls, type(Tuple[Uint, ...])) and cls._name == "Tuple": # type: ignore # noqa: E501 + ensure(isinstance(raw_rlp, list), RLPDecodingError) + if cls.__args__[1] == ...: # type: ignore + args = [] + for raw_item in raw_rlp: + args.append(_decode_to(cls.__args__[0], raw_item)) # type: ignore # noqa: E501 + return tuple(args) # type: ignore + else: + args = [] + ensure(len(raw_rlp) == len(cls.__args__), RLPDecodingError) # type: ignore # noqa: E501 + for t, raw_item in zip(cls.__args__, raw_rlp): # type: ignore + args.append(_decode_to(t, raw_item)) + return tuple(args) # type: ignore + elif cls == Union[Bytes0, Bytes20]: + # We can't support Union types in general, so we support this one + # (which appears in the Transaction type) as a special case + ensure(isinstance(raw_rlp, Bytes), RLPDecodingError) + if len(raw_rlp) == 0: + return Bytes0() # type: ignore + elif len(raw_rlp) == 20: + return Bytes20(raw_rlp) # type: ignore + else: + raise RLPDecodingError( + "Bytes has length {}, expected 0 or 20".format(len(raw_rlp)) + ) + elif isinstance(cls, type(List[Bytes])) and cls._name == "List": # type: ignore # noqa: E501 + ensure(isinstance(raw_rlp, list), RLPDecodingError) + items = [] + for raw_item in raw_rlp: + items.append(_decode_to(cls.__args__[0], raw_item)) # type: ignore + return items # type: ignore + elif isinstance(cls, type(Union[Bytes, List[Bytes]])) and cls.__origin__ == Union: # type: ignore # noqa: E501 + if len(cls.__args__) != 2 or Bytes not in cls.__args__: # type: ignore + raise RLPDecodingError( + "RLP Decoding to type {} is not supported".format(cls) + ) + if isinstance(raw_rlp, Bytes): + return raw_rlp # type: ignore + elif cls.__args__[0] == Bytes: # type: ignore + return _decode_to(cls.__args__[1], raw_rlp) # type: ignore + else: + return _decode_to(cls.__args__[0], raw_rlp) # type: ignore + elif issubclass(cls, bool): + if raw_rlp == b"\x01": + return cls(True) # type: ignore + elif raw_rlp == b"": + return cls(False) # type: ignore + else: + raise TypeError("Cannot decode {} as {}".format(raw_rlp, cls)) + elif issubclass(cls, FixedBytes): + ensure(isinstance(raw_rlp, Bytes), RLPDecodingError) + ensure(len(raw_rlp) == cls.LENGTH, RLPDecodingError) + return cls(raw_rlp) # type: ignore + elif issubclass(cls, Bytes): + ensure(isinstance(raw_rlp, Bytes), RLPDecodingError) + return raw_rlp + elif issubclass(cls, (Uint, FixedUint)): + ensure(isinstance(raw_rlp, Bytes), RLPDecodingError) + try: + return cls.from_be_bytes(raw_rlp) # type: ignore + except ValueError: + raise RLPDecodingError + elif is_dataclass(cls): + ensure(isinstance(raw_rlp, list), RLPDecodingError) + assert isinstance(raw_rlp, list) + args = [] + ensure(len(fields(cls)) == len(raw_rlp), RLPDecodingError) + for field, rlp_item in zip(fields(cls), raw_rlp): + args.append(_decode_to(field.type, rlp_item)) + return cast(T, cls(*args)) + else: + raise RLPDecodingError( + "RLP Decoding to type {} is not supported".format(cls) + ) + + +def decode_to_bytes(encoded_bytes: Bytes) -> Bytes: + """ + Decodes a rlp encoded byte stream assuming that the decoded data + should be of type `bytes`. + + Parameters + ---------- + encoded_bytes : + RLP encoded byte stream. + + Returns + ------- + decoded : `ethereum.base_types.Bytes` + RLP decoded Bytes data + """ + if len(encoded_bytes) == 1 and encoded_bytes[0] < 0x80: + return encoded_bytes + elif encoded_bytes[0] <= 0xB7: + len_raw_data = encoded_bytes[0] - 0x80 + ensure(len_raw_data < len(encoded_bytes), RLPDecodingError) + raw_data = encoded_bytes[1 : 1 + len_raw_data] + ensure( + not (len_raw_data == 1 and raw_data[0] < 0x80), RLPDecodingError + ) + return raw_data + else: + # This is the index in the encoded data at which decoded data + # starts from. + decoded_data_start_idx = 1 + encoded_bytes[0] - 0xB7 + ensure( + decoded_data_start_idx - 1 < len(encoded_bytes), RLPDecodingError + ) + # Expectation is that the big endian bytes shouldn't start with 0 + # while trying to decode using RLP, in which case is an error. + ensure(encoded_bytes[1] != 0, RLPDecodingError) + len_decoded_data = Uint.from_be_bytes( + encoded_bytes[1:decoded_data_start_idx] + ) + ensure(len_decoded_data >= 0x38, RLPDecodingError) + decoded_data_end_idx = decoded_data_start_idx + len_decoded_data + ensure(decoded_data_end_idx - 1 < len(encoded_bytes), RLPDecodingError) + return encoded_bytes[decoded_data_start_idx:decoded_data_end_idx] + + +def decode_to_sequence(encoded_sequence: Bytes) -> List[RLP]: + """ + 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`. + """ + if encoded_sequence[0] <= 0xF7: + len_joined_encodings = encoded_sequence[0] - 0xC0 + ensure(len_joined_encodings < len(encoded_sequence), RLPDecodingError) + joined_encodings = encoded_sequence[1 : 1 + len_joined_encodings] + else: + joined_encodings_start_idx = 1 + encoded_sequence[0] - 0xF7 + ensure( + joined_encodings_start_idx - 1 < len(encoded_sequence), + RLPDecodingError, + ) + # Expectation is that the big endian bytes shouldn't start with 0 + # while trying to decode using RLP, in which case is an error. + ensure(encoded_sequence[1] != 0, RLPDecodingError) + len_joined_encodings = Uint.from_be_bytes( + encoded_sequence[1:joined_encodings_start_idx] + ) + ensure(len_joined_encodings >= 0x38, RLPDecodingError) + joined_encodings_end_idx = ( + joined_encodings_start_idx + len_joined_encodings + ) + ensure( + joined_encodings_end_idx - 1 < len(encoded_sequence), + RLPDecodingError, + ) + joined_encodings = encoded_sequence[ + joined_encodings_start_idx:joined_encodings_end_idx + ] + + return decode_joined_encodings(joined_encodings) + + +def decode_joined_encodings(joined_encodings: Bytes) -> List[RLP]: + """ + 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`. + """ + decoded_sequence = [] + + item_start_idx = 0 + while item_start_idx < len(joined_encodings): + encoded_item_length = decode_item_length( + joined_encodings[item_start_idx:] + ) + ensure( + item_start_idx + encoded_item_length - 1 < len(joined_encodings), + RLPDecodingError, + ) + encoded_item = joined_encodings[ + item_start_idx : item_start_idx + encoded_item_length + ] + decoded_sequence.append(decode(encoded_item)) + item_start_idx += encoded_item_length + + return decoded_sequence + + +def decode_item_length(encoded_data: Bytes) -> int: + """ + Find the length of the rlp encoding for the first object in the + encoded sequence. + Here `encoded_data` refers to concatenation of rlp encoding for each + item in a sequence. + + NOTE - This is a helper function not described in the spec. It was + introduced as the spec doesn't discuss about decoding the RLP encoded + data. + + Parameters + ---------- + encoded_data : + RLP encoded data for a sequence of objects. + + Returns + ------- + rlp_length : `int` + """ + # Can't decode item length for empty encoding + ensure(len(encoded_data) > 0, RLPDecodingError) + + first_rlp_byte = Uint(encoded_data[0]) + + # This is the length of the big endian representation of the length of + # rlp encoded object byte stream. + length_length = Uint(0) + decoded_data_length = 0 + + # This occurs only when the raw_data is a single byte whose value < 128 + if first_rlp_byte < 0x80: + # We return 1 here, as the end formula + # 1 + length_length + decoded_data_length would be invalid for + # this case. + return 1 + # This occurs only when the raw_data is a byte stream with length < 56 + # and doesn't fall into the above cases + elif first_rlp_byte <= 0xB7: + decoded_data_length = first_rlp_byte - 0x80 + # This occurs only when the raw_data is a byte stream and doesn't fall + # into the above cases + elif first_rlp_byte <= 0xBF: + length_length = first_rlp_byte - 0xB7 + ensure(length_length < len(encoded_data), RLPDecodingError) + # Expectation is that the big endian bytes shouldn't start with 0 + # while trying to decode using RLP, in which case is an error. + ensure(encoded_data[1] != 0, RLPDecodingError) + decoded_data_length = Uint.from_be_bytes( + encoded_data[1 : 1 + length_length] + ) + # This occurs only when the raw_data is a sequence of objects with + # length(concatenation of encoding of each object) < 56 + elif first_rlp_byte <= 0xF7: + decoded_data_length = first_rlp_byte - 0xC0 + # This occurs only when the raw_data is a sequence of objects and + # doesn't fall into the above cases. + elif first_rlp_byte <= 0xFF: + length_length = first_rlp_byte - 0xF7 + ensure(length_length < len(encoded_data), RLPDecodingError) + # Expectation is that the big endian bytes shouldn't start with 0 + # while trying to decode using RLP, in which case is an error. + ensure(encoded_data[1] != 0, RLPDecodingError) + decoded_data_length = Uint.from_be_bytes( + encoded_data[1 : 1 + length_length] + ) + + return 1 + length_length + decoded_data_length + + +def rlp_hash(data: RLP) -> Hash32: + """ + Obtain the keccak-256 hash of the rlp encoding of the passed in data. + + Parameters + ---------- + data : + The data for which we need the rlp hash. + + Returns + ------- + hash : `Hash32` + The rlp hash of the passed in data. + """ + return keccak256(encode(data)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/__init__.md b/docs/revm-python-spec/revm-verif/spec/shanghai/__init__.md new file mode 100644 index 00000000..57bdf042 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/__init__.md @@ -0,0 +1,15 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByTimestamp + +FORK_CRITERIA = ByTimestamp(1681338455) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/blocks.md b/docs/revm-python-spec/revm-verif/spec/shanghai/blocks.md new file mode 100644 index 00000000..7e0e0cdb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/blocks.md @@ -0,0 +1,108 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from ..base_types import ( + U64, + U256, + Bytes, + Bytes8, + Bytes32, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import LegacyTransaction + + +@slotted_freezable +@dataclass +class Withdrawal: + """ + Withdrawals that have been validated on the consensus layer. + """ + + index: U64 + validator_index: U64 + address: Address + amount: U256 + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + prev_randao: Bytes32 + nonce: Bytes8 + base_fee_per_gas: Uint + withdrawals_root: Root + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Union[Bytes, LegacyTransaction], ...] + ommers: Tuple[Header, ...] + withdrawals: Tuple[Withdrawal, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + succeeded: bool + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/bloom.md b/docs/revm-python-spec/revm-verif/spec/shanghai/bloom.md new file mode 100644 index 00000000..398f63de --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/fork.md b/docs/revm-python-spec/revm-verif/spec/shanghai/fork.md new file mode 100644 index 00000000..f465a3ad --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/fork.md @@ -0,0 +1,1010 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Tuple, Union + +from ethereum.base_types import Bytes0, Bytes32 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, Bytes, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt, Withdrawal +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + destroy_account, + get_account, + increment_nonce, + process_withdrawal, + set_account_balance, + state_root, +) +from .transactions import ( + TX_ACCESS_LIST_ADDRESS_COST, + TX_ACCESS_LIST_STORAGE_KEY_COST, + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + AccessListTransaction, + FeeMarketTransaction, + LegacyTransaction, + Transaction, + decode_transaction, + encode_transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.gas import init_code_cost +from .vm.interpreter import MAX_CODE_SIZE, process_message_call + +BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 +ELASTICITY_MULTIPLIER = 2 +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +EMPTY_OMMER_HASH = keccak256(rlp.encode([])) + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + ensure(block.ommers == (), InvalidBlock) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + ensure( + apply_body_output.withdrawals_root == block.header.withdrawals_root, + InvalidBlock, + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def calculate_base_fee_per_gas( + block_gas_limit: Uint, + parent_gas_limit: Uint, + parent_gas_used: Uint, + parent_base_fee_per_gas: Uint, +) -> Uint: + """ + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + """ + parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER + + ensure( + check_gas_limit(block_gas_limit, parent_gas_limit), + InvalidBlock, + ) + + if parent_gas_used == parent_gas_target: + expected_base_fee_per_gas = parent_base_fee_per_gas + elif parent_gas_used > parent_gas_target: + gas_used_delta = parent_gas_used - parent_gas_target + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = max( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, + 1, + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas + base_fee_per_gas_delta + ) + else: + gas_used_delta = parent_gas_target - parent_gas_used + + parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta + target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target + + base_fee_per_gas_delta = ( + target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR + ) + + expected_base_fee_per_gas = ( + parent_base_fee_per_gas - base_fee_per_gas_delta + ) + + return Uint(expected_base_fee_per_gas) + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.gas_used <= header.gas_limit, InvalidBlock) + + 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, + ) + + ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) + + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + ensure(header.difficulty == 0, InvalidBlock) + ensure(header.nonce == b"\x00\x00\x00\x00\x00\x00\x00\x00", InvalidBlock) + ensure(header.ommers_hash == EMPTY_OMMER_HASH, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + +def check_transaction( + tx: Transaction, + base_fee_per_gas: Uint, + gas_available: Uint, + chain_id: U64, +) -> Tuple[Address, Uint]: + """ + 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. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + if isinstance(tx, FeeMarketTransaction): + ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock) + ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock) + + priority_fee_per_gas = min( + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas - base_fee_per_gas, + ) + effective_gas_price = priority_fee_per_gas + base_fee_per_gas + else: + ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock) + effective_gas_price = tx.gas_price + + return sender_address, effective_gas_price + + +def make_receipt( + tx: Transaction, + error: Optional[Exception], + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Union[Bytes, Receipt]: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + succeeded=error is None, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + if isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(receipt) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(receipt) + else: + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + withdrawals_root : `ethereum.fork_types.Root` + Trie root of all the withdrawals in the block. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + withdrawals_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + base_fee_per_gas: Uint, + block_gas_limit: Uint, + block_time: U256, + prev_randao: Bytes32, + transactions: Tuple[Union[LegacyTransaction, Bytes], ...], + chain_id: U64, + withdrawals: Tuple[Withdrawal, ...], +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + prev_randao : + The previous randao from the beacon chain. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + withdrawals : + Withdrawals to be processed in the current block. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[ + Bytes, Optional[Union[Bytes, LegacyTransaction]] + ] = Trie(secured=False, default=None) + receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( + secured=False, default=None + ) + withdrawals_trie: Trie[Bytes, Optional[Union[Bytes, Withdrawal]]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(map(decode_transaction, transactions)): + trie_set( + transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) + ) + + sender_address, effective_gas_price = check_transaction( + tx, base_fee_per_gas, gas_available, chain_id + ) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + base_fee_per_gas=base_fee_per_gas, + gas_price=effective_gas_price, + time=block_time, + prev_randao=prev_randao, + state=state, + chain_id=chain_id, + traces=[], + ) + + gas_used, logs, error = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, error, (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + for i, wd in enumerate(withdrawals): + trie_set(withdrawals_trie, rlp.encode(Uint(i)), rlp.encode(wd)) + + process_withdrawal(state, wd) + + if account_exists_and_is_empty(state, wd.address): + destroy_account(state, wd.address) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + root(withdrawals_trie), + ) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + + if isinstance(tx, FeeMarketTransaction): + max_gas_fee = tx.gas * tx.max_fee_per_gas + else: + max_gas_fee = tx.gas * tx.gas_price + + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + effective_gas_fee = tx.gas * env.gas_price + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + + sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + preaccessed_addresses = set() + preaccessed_storage_keys = set() + preaccessed_addresses.add(env.coinbase) + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for address, keys in tx.access_list: + preaccessed_addresses.add(address) + for key in keys: + preaccessed_storage_keys.add((address, key)) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + preaccessed_addresses=frozenset(preaccessed_addresses), + preaccessed_storage_keys=frozenset(preaccessed_storage_keys), + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 5, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price + + # For non-1559 transactions env.gas_price == tx.gas_price + priority_fee_per_gas = env.gas_price - env.base_fee_per_gas + transaction_fee = ( + tx.gas - output.gas_left - gas_refund + ) * priority_fee_per_gas + + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs, output.error + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + if calculate_intrinsic_cost(tx) > tx.gas: + return False + if tx.nonce >= 2**64 - 1: + return False + if tx.to == Bytes0(b"") and len(tx.data) > 2 * MAX_CODE_SIZE: + return False + + return True + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + int(init_code_cost(Uint(len(tx.data)))) + else: + create_cost = 0 + + access_list_cost = 0 + if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): + for _address, keys in tx.access_list: + access_list_cost += TX_ACCESS_LIST_ADDRESS_COST + access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + + return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + r, s = tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + ensure( + v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock + ) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_2930(tx) + ) + elif isinstance(tx, FeeMarketTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_1559(tx) + ) + + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def signing_hash_2930(tx: AccessListTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x01" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + b"\x02" + + rlp.encode( + ( + tx.chain_id, + tx.nonce, + tx.max_priority_fee_per_gas, + tx.max_fee_per_gas, + tx.gas, + tx.to, + tx.value, + tx.data, + tx.access_list, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/fork_types.md b/docs/revm-python-spec/revm-verif/spec/shanghai/fork_types.md new file mode 100644 index 00000000..fb7b7534 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/state.md b/docs/revm-python-spec/revm-verif/spec/shanghai/state.md new file mode 100644 index 00000000..c96a3189 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/state.md @@ -0,0 +1,612 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .blocks import Withdrawal +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + _created_accounts: Set[Address] = field(default_factory=set) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + del state._created_accounts + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + if not state._snapshots: + state._created_accounts.clear() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def mark_account_created(state: State, address: Address) -> None: + """ + 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. + """ + state._created_accounts.add(address) + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def process_withdrawal( + state: State, + wd: Withdrawal, +) -> None: + """ + Increase the balance of the withdrawing account. + """ + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += wd.amount * 10**9 + + modify_state(state, wd.address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def get_storage_original(state: State, address: Address, key: Bytes) -> U256: + """ + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + """ + # In the transaction where an account is created, its preexisting storage + # is ignored. + if address in state._created_accounts: + return U256(0) + + _, original_trie = state._snapshots[0] + original_account_trie = original_trie.get(address) + + if original_account_trie is None: + original_value = U256(0) + else: + original_value = trie_get(original_account_trie, key) + + assert isinstance(original_value, U256) + + return original_value +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/transactions.md b/docs/revm-python-spec/revm-verif/spec/shanghai/transactions.md new file mode 100644 index 00000000..08eb37f4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/transactions.md @@ -0,0 +1,126 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple, Union + +from .. import rlp +from ..base_types import ( + U64, + U256, + Bytes, + Bytes0, + Bytes32, + Uint, + slotted_freezable, +) +from ..exceptions import InvalidBlock +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 +TX_ACCESS_LIST_ADDRESS_COST = 2400 +TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 + + +@slotted_freezable +@dataclass +class LegacyTransaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class AccessListTransaction: + """ + The transaction type added in EIP-2930 to support access lists. + """ + + chain_id: U64 + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +@slotted_freezable +@dataclass +class FeeMarketTransaction: + """ + The transaction type added in EIP-1559. + """ + + chain_id: U64 + nonce: U256 + max_priority_fee_per_gas: Uint + max_fee_per_gas: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + y_parity: U256 + r: U256 + s: U256 + + +Transaction = Union[ + LegacyTransaction, AccessListTransaction, FeeMarketTransaction +] + + +def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: + """ + Encode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, LegacyTransaction): + return tx + elif isinstance(tx, AccessListTransaction): + return b"\x01" + rlp.encode(tx) + elif isinstance(tx, FeeMarketTransaction): + return b"\x02" + rlp.encode(tx) + else: + raise Exception(f"Unable to encode transaction of type {type(tx)}") + + +def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: + """ + Decode a transaction. Needed because non-legacy transactions aren't RLP. + """ + if isinstance(tx, Bytes): + if tx[0] == 1: + return rlp.decode_to(AccessListTransaction, tx[1:]) + elif tx[0] == 2: + return rlp.decode_to(FeeMarketTransaction, tx[1:]) + else: + raise InvalidBlock + else: + return tx +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/trie.md b/docs/revm-python-spec/revm-verif/spec/shanghai/trie.md new file mode 100644 index 00000000..d70c5e87 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/trie.md @@ -0,0 +1,473 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.paris import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt, Withdrawal +from .fork_types import Account, Address, Root, encode_account +from .transactions import LegacyTransaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[ + Account, Bytes, LegacyTransaction, Receipt, Uint, U256, Withdrawal, None +] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Union[LegacyTransaction, Bytes]], + Optional[Union[Receipt, Bytes]], + Optional[Union[Withdrawal, Bytes]], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (LegacyTransaction, Receipt, Withdrawal, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/shanghai/utils/__init__.md new file mode 100644 index 00000000..af3e853b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/utils/address.md b/docs/revm-python-spec/revm-verif/spec/shanghai/utils/address.md new file mode 100644 index 00000000..58e05859 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/utils/address.md @@ -0,0 +1,97 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this shanghai version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Bytes32, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) + + +def compute_create2_contract_address( + address: Address, salt: Bytes32, call_data: bytearray +) -> Address: + """ + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.shanghai.fork_types.Address` + The computed address of the new account. + """ + preimage = b"\xff" + address + salt + keccak256(call_data) + computed_address = keccak256(preimage) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/shanghai/utils/hexadecimal.md new file mode 100644 index 00000000..28fdcd19 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Shanghai types. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/utils/message.md b/docs/revm-python-spec/revm-verif/spec/shanghai/utils/message.md new file mode 100644 index 00000000..56fa7ded --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/utils/message.md @@ -0,0 +1,121 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/utils/message.py) + +```python +""" +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. +""" +from typing import FrozenSet, Optional, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Bytes32, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, + is_static: bool = False, + preaccessed_addresses: FrozenSet[Address] = frozenset(), + preaccessed_storage_keys: FrozenSet[ + Tuple[(Address, Bytes32)] + ] = frozenset(), +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.shanghai.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + accessed_addresses = set() + accessed_addresses.add(current_target) + accessed_addresses.add(caller) + accessed_addresses.update(PRE_COMPILED_CONTRACTS.keys()) + accessed_addresses.update(preaccessed_addresses) + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=is_static, + accessed_addresses=accessed_addresses, + accessed_storage_keys=set(preaccessed_storage_keys), + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/__init__.md new file mode 100644 index 00000000..60a88961 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/__init__.md @@ -0,0 +1,152 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U64, U256, Bytes, Bytes0, Bytes32, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + base_fee_per_gas: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + prev_randao: Bytes32 + state: State + chain_id: U64 + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + is_static: bool + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: int + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + return_data: Bytes + error: Optional[Exception] + accessed_addresses: Set[Address] + accessed_storage_keys: Set[Tuple[Address, Bytes32]] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + evm.accessed_addresses.update(child_evm.accessed_addresses) + evm.accessed_storage_keys.update(child_evm.accessed_storage_keys) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/exceptions.md new file mode 100644 index 00000000..b4bc3055 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/exceptions.md @@ -0,0 +1,138 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class Revert(EthereumException): + """ + Raised by the `REVERT` opcode. + + Unlike other EVM exceptions this does not result in the consumption of all + gas. + """ + + pass + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class WriteInStaticContext(ExceptionalHalt): + """ + Raised when an attempt is made to modify the state while operating inside + of a STATICCALL context. + """ + + pass + + +class OutOfBoundsRead(ExceptionalHalt): + """ + Raised when an attempt was made to read data beyond the + boundaries of the buffer. + """ + + pass + + +class InvalidParameter(ExceptionalHalt): + """ + Raised when invalid parameters are passed. + """ + + pass + + +class InvalidContractPrefix(ExceptionalHalt): + """ + Raised when the new contract code starts with 0xEF. + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/gas.md new file mode 100644 index 00000000..d6db1aa5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/gas.md @@ -0,0 +1,265 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(4800) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) +GAS_RETURN_DATA_COPY = Uint(3) +GAS_FAST_STEP = Uint(5) +GAS_BLAKE2_PER_ROUND = Uint(1) +GAS_COLD_SLOAD = Uint(2100) +GAS_COLD_ACCOUNT_ACCESS = Uint(2600) +GAS_WARM_ACCESS = Uint(100) +GAS_INIT_CODE_WORD_COST = 2 + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) + + +def init_code_cost(init_code_length: Uint) -> Uint: + """ + Calculates the gas to be charged for the init code in CREAT* + opcodes as well as create transactions. + + Parameters + ---------- + init_code_length : + The length of the init code provided to the opcode + or a create transaction + + Returns + ------- + init_code_gas: `ethereum.base_types.Uint` + The gas to be charged for the init code. + """ + return GAS_INIT_CODE_WORD_COST * ceil32(init_code_length) // 32 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/__init__.md new file mode 100644 index 00000000..e2484a43 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/__init__.md @@ -0,0 +1,362 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + SHL = 0x1B + SHR = 0x1C + SAR = 0x1D + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + RETURNDATASIZE = 0x3D + RETURNDATACOPY = 0x3E + EXTCODEHASH = 0x3F + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + PREVRANDAO = 0x44 + GASLIMIT = 0x45 + CHAINID = 0x46 + SELFBALANCE = 0x47 + BASEFEE = 0x48 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH0 = 0x5F + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + STATICCALL = 0xFA + REVERT = 0xFD + SELFDESTRUCT = 0xFF + CREATE2 = 0xF5 + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.SHL: bitwise_instructions.bitwise_shl, + Ops.SHR: bitwise_instructions.bitwise_shr, + Ops.SAR: bitwise_instructions.bitwise_sar, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.PREVRANDAO: block_instructions.prev_randao, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.CHAINID: block_instructions.chain_id, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.RETURNDATASIZE: environment_instructions.returndatasize, + Ops.RETURNDATACOPY: environment_instructions.returndatacopy, + Ops.EXTCODEHASH: environment_instructions.extcodehash, + Ops.SELFBALANCE: environment_instructions.self_balance, + Ops.BASEFEE: environment_instructions.base_fee, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH0: stack_instructions.push0, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, + Ops.STATICCALL: system_instructions.staticcall, + Ops.REVERT: system_instructions.revert, + Ops.CREATE2: system_instructions.create2, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/arithmetic.md new file mode 100644 index 00000000..3861eaa5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/bitwise.md new file mode 100644 index 00000000..1e99137a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/bitwise.md @@ -0,0 +1,246 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256, U256_CEIL_VALUE + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shl(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256((value << shift) % U256_CEIL_VALUE) + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_shr(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = value >> shift + else: + result = U256(0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_sar(evm: Evm) -> None: + """ + 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. + """ + # STACK + shift = pop(evm.stack) + signed_value = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if shift < 256: + result = U256.from_signed(signed_value >> shift) + elif signed_value >= 0: + result = U256(0) + else: + result = U256.MAX_VALUE + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/block.md new file mode 100644 index 00000000..e8e3dd66 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/block.md @@ -0,0 +1,254 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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`. + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def prev_randao(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.prev_randao)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def chain_id(evm: Evm) -> None: + """ + 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`. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.chain_id)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/comparison.md new file mode 100644 index 00000000..7fe25cf6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/control_flow.md new file mode 100644 index 00000000..f3db7131 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/environment.md new file mode 100644 index 00000000..3cb1bf9d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/environment.md @@ -0,0 +1,543 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import EMPTY_ACCOUNT +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..exceptions import OutOfBoundsRead +from ..gas import ( + GAS_BASE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_COPY, + GAS_FAST_STEP, + GAS_RETURN_DATA_COPY, + GAS_VERY_LOW, + GAS_WARM_ACCESS, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) + else: + evm.accessed_addresses.add(address) + charge_gas( + evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatasize(evm: Evm) -> None: + """ + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.return_data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def returndatacopy(evm: Evm) -> None: + """ + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_index = pop(evm.stack) + return_data_start_position = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_RETURN_DATA_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + ensure( + Uint(return_data_start_position) + Uint(size) <= len(evm.return_data), + OutOfBoundsRead, + ) + + evm.memory += b"\x00" * extend_memory.expand_by + value = evm.return_data[ + return_data_start_position : return_data_start_position + size + ] + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodehash(evm: Evm) -> None: + """ + Returns the keccak256 hash of a contractโ€™s bytecode + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + if address in evm.accessed_addresses: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_addresses.add(address) + charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + + # OPERATION + account = get_account(evm.env.state, address) + + if account == EMPTY_ACCOUNT: + codehash = U256(0) + else: + codehash = U256.from_be_bytes(keccak256(account.code)) + + push(evm.stack, codehash) + + # PROGRAM COUNTER + evm.pc += 1 + + +def self_balance(evm: Evm) -> None: + """ + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_FAST_STEP) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, evm.message.current_target).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def base_fee(evm: Evm) -> None: + """ + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.base_fee_per_gas)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/keccak.md new file mode 100644 index 00000000..63db28ed --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/log.md new file mode 100644 index 00000000..25a2deaf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/log.md @@ -0,0 +1,94 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from ...blocks import Log +from .. import Evm +from ..exceptions import WriteInStaticContext +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + ensure(not evm.message.is_static, WriteInStaticContext) + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/memory.md new file mode 100644 index 00000000..40043828 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/stack.md new file mode 100644 index 00000000..d800c53f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/stack.md @@ -0,0 +1,218 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + if num_bytes == 0: + charge_gas(evm, GAS_BASE) + else: + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push0 = partial(push_n, num_bytes=0) +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/storage.md new file mode 100644 index 00000000..21cedf51 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/storage.md @@ -0,0 +1,132 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" +from ethereum.base_types import Uint +from ethereum.utils.ensure import ensure + +from ...state import get_storage, get_storage_original, set_storage +from .. import Evm +from ..exceptions import OutOfGasError, WriteInStaticContext +from ..gas import ( + GAS_CALL_STIPEND, + GAS_COLD_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + GAS_WARM_ACCESS, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + if (evm.message.current_target, key) in evm.accessed_storage_keys: + charge_gas(evm, GAS_WARM_ACCESS) + else: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + charge_gas(evm, GAS_COLD_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + ensure(evm.gas_left > GAS_CALL_STIPEND, OutOfGasError) + + original_value = get_storage_original( + evm.env.state, evm.message.current_target, key + ) + current_value = get_storage(evm.env.state, evm.message.current_target, key) + + gas_cost = Uint(0) + + if (evm.message.current_target, key) not in evm.accessed_storage_keys: + evm.accessed_storage_keys.add((evm.message.current_target, key)) + gas_cost += GAS_COLD_SLOAD + + if original_value == current_value and current_value != new_value: + if original_value == 0: + gas_cost += GAS_STORAGE_SET + else: + gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD + else: + gas_cost += GAS_WARM_ACCESS + + # Refund Counter Calculation + if current_value != new_value: + if original_value != 0 and current_value != 0 and new_value == 0: + # Storage is cleared for the first time in the transaction + evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND) + + if original_value != 0 and current_value == 0: + # Gas refund issued earlier to be reversed + evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND) + + if original_value == new_value: + # Storage slot being restored to its original value + if original_value == 0: + # Slot was originally empty and was SET earlier + evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + else: + # Slot was originally non-empty and was UPDATED earlier + evm.refund_counter += int( + GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS + ) + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/system.md new file mode 100644 index 00000000..fd7e2b45 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/instructions/system.md @@ -0,0 +1,692 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.utils.ensure import ensure +from ethereum.utils.numeric import ceil32 + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import ( + compute_contract_address, + compute_create2_contract_address, + to_address, +) +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..exceptions import OutOfGasError, Revert, WriteInStaticContext +from ..gas import ( + GAS_CALL_VALUE, + GAS_COLD_ACCOUNT_ACCESS, + GAS_CREATE, + GAS_KECCAK256_WORD, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_WARM_ACCESS, + GAS_ZERO, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + init_code_cost, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def generic_create( + evm: Evm, + endowment: U256, + contract_address: Address, + memory_start_position: U256, + memory_size: U256, + init_code_gas: Uint, +) -> None: + """ + Core logic used by the `CREATE*` family of opcodes. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import ( + MAX_CODE_SIZE, + STACK_DEPTH_LIMIT, + process_create_message, + ) + + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + ensure(len(call_data) <= 2 * MAX_CODE_SIZE, OutOfGasError) + + evm.accessed_addresses.add(contract_address) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + ensure(not evm.message.is_static, WriteInStaticContext) + evm.return_data = b"" + + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + evm.gas_left += create_message_gas + push(evm.stack, U256(0)) + return + + if account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + return + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + is_static=False, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = b"" + push(evm.stack, U256.from_be_bytes(child_evm.message.current_target)) + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + init_code_gas = init_code_cost(Uint(memory_size)) + + charge_gas(evm, GAS_CREATE + extend_memory.cost + init_code_gas) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + generic_create( + evm, + endowment, + contract_address, + memory_start_position, + memory_size, + init_code_gas, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def create2(evm: Evm) -> None: + """ + 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. + """ + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + salt = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + call_data_words = ceil32(Uint(memory_size)) // 32 + init_code_gas = init_code_cost(Uint(memory_size)) + charge_gas( + evm, + GAS_CREATE + + GAS_KECCAK256_WORD * call_data_words + + extend_memory.cost + + init_code_gas, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + contract_address = compute_create2_contract_address( + evm.message.current_target, + salt, + memory_read_bytes(evm.memory, memory_start_position, memory_size), + ) + + generic_create( + evm, + endowment, + contract_address, + memory_start_position, + memory_size, + init_code_gas, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + evm.return_data = b"" + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + is_static=True if is_staticcall else evm.message.is_static, + accessed_addresses=evm.accessed_addresses.copy(), + accessed_storage_keys=evm.accessed_storage_keys.copy(), + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + evm.return_data = child_evm.output + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + create_gas_cost = ( + Uint(0) + if is_account_alive(evm.env.state, to) or value == 0 + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + ensure(not evm.message.is_static or value == U256(0), WriteInStaticContext) + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.return_data = b"" + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if beneficiary not in evm.accessed_addresses: + evm.accessed_addresses.add(beneficiary) + gas_cost += GAS_COLD_ACCOUNT_ACCESS + + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + charge_gas(evm, gas_cost) + + # OPERATION + ensure(not evm.message.is_static, WriteInStaticContext) + + originator = evm.message.current_target + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if code_address in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(code_address) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def staticcall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + + if to in evm.accessed_addresses: + access_gas_cost = GAS_WARM_ACCESS + else: + evm.accessed_addresses.add(to) + access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + + message_call_gas = calculate_message_call_gas( + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + U256(0), + evm.message.current_target, + to, + to, + True, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def revert(evm: Evm) -> None: + """ + 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. + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + + charge_gas(evm, extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + output = memory_read_bytes(evm.memory, memory_start_index, size) + evm.output = bytes(output) + raise Revert + + # PROGRAM COUNTER + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/interpreter.md new file mode 100644 index 00000000..909d2af4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/interpreter.md @@ -0,0 +1,314 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + mark_account_created, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidContractPrefix, + InvalidOpcode, + OutOfGasError, + Revert, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Union[Tuple[()], Tuple[Log, ...]] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = U256(evm.refund_counter) + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.shanghai.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by a `CREATE` call collides with a subsequent + # `CREATE` or `CREATE2` call. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + # In the previously mentioned edge case the preexisting storage is ignored + # for gas refund purposes. In order to do this we must track created + # accounts. + mark_account_created(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + if len(contract_code) > 0: + ensure(contract_code[0] != 0xEF, InvalidContractPrefix) + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.shanghai.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=0, + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + return_data=b"", + error=None, + accessed_addresses=message.accessed_addresses, + accessed_storage_keys=message.accessed_storage_keys, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.output = b"" + evm.error = error + except Revert as error: + evm_trace(evm, OpException(error)) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/memory.md new file mode 100644 index 00000000..b0774328 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..c7f353e6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/__init__.md @@ -0,0 +1,44 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", + "MODEXP_ADDRESS", + "ALT_BN128_ADD_ADDRESS", + "ALT_BN128_MUL_ADDRESS", + "ALT_BN128_PAIRING_CHECK_ADDRESS", + "BLAKE2F_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +MODEXP_ADDRESS = hex_to_address("0x05") +ALT_BN128_ADD_ADDRESS = hex_to_address("0x06") +ALT_BN128_MUL_ADDRESS = hex_to_address("0x07") +ALT_BN128_PAIRING_CHECK_ADDRESS = hex_to_address("0x08") +BLAKE2F_ADDRESS = hex_to_address("0x09") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/alt_bn128.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/alt_bn128.md new file mode 100644 index 00000000..0cc6486e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/alt_bn128.md @@ -0,0 +1,162 @@ +# ๐Ÿ alt_bn128.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.py) + +```python +""" +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +""" +from ethereum.base_types import U256, Uint +from ethereum.crypto.alt_bn128 import ( + ALT_BN128_CURVE_ORDER, + ALT_BN128_PRIME, + BNF, + BNF2, + BNF12, + BNP, + BNP2, + pairing, +) +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import charge_gas +from ...vm.memory import buffer_read +from ..exceptions import OutOfGasError + + +def alt_bn128_add(evm: Evm) -> None: + """ + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(150)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + x1_bytes = buffer_read(data, U256(64), U256(32)) + x1_value = U256.from_be_bytes(x1_bytes) + y1_bytes = buffer_read(data, U256(96), U256(32)) + y1_value = U256.from_be_bytes(y1_bytes) + + for i in (x0_value, y0_value, x1_value, y1_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + p1 = BNP(BNF(x1_value), BNF(y1_value)) + except ValueError: + raise OutOfGasError + + p = p0 + p1 + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_mul(evm: Evm) -> None: + """ + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(6000)) + + # OPERATION + x0_bytes = buffer_read(data, U256(0), U256(32)) + x0_value = U256.from_be_bytes(x0_bytes) + y0_bytes = buffer_read(data, U256(32), U256(32)) + y0_value = U256.from_be_bytes(y0_bytes) + n = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + for i in (x0_value, y0_value): + if i >= ALT_BN128_PRIME: + raise OutOfGasError + + try: + p0 = BNP(BNF(x0_value), BNF(y0_value)) + except ValueError: + raise OutOfGasError + + p = p0.mul_by(n) + + evm.output = p.x.to_be_bytes32() + p.y.to_be_bytes32() + + +def alt_bn128_pairing_check(evm: Evm) -> None: + """ + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + + # OPERATION + if len(data) % 192 != 0: + raise OutOfGasError + result = BNF12.from_int(1) + for i in range(len(data) // 192): + values = [] + for j in range(6): + value = U256.from_be_bytes( + data[i * 192 + 32 * j : i * 192 + 32 * (j + 1)] + ) + if value >= ALT_BN128_PRIME: + raise OutOfGasError + values.append(int(value)) + + try: + p = BNP(BNF(values[0]), BNF(values[1])) + q = BNP2( + BNF2((values[3], values[2])), BNF2((values[5], values[4])) + ) + except ValueError: + raise OutOfGasError() + ensure( + p.mul_by(ALT_BN128_CURVE_ORDER) == BNP.point_at_infinity(), + OutOfGasError, + ) + ensure( + q.mul_by(ALT_BN128_CURVE_ORDER) == BNP2.point_at_infinity(), + OutOfGasError, + ) + if p != BNP.point_at_infinity() and q != BNP2.point_at_infinity(): + result = result * pairing(q, p) + + if result == BNF12.from_int(1): + evm.output = U256(1).to_be_bytes32() + else: + evm.output = U256(0).to_be_bytes32() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/blake2f.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/blake2f.md new file mode 100644 index 00000000..611f7c50 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/blake2f.md @@ -0,0 +1,50 @@ +# ๐Ÿ blake2f.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/precompiled_contracts/blake2f.py) + +```python +""" +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +""" +from ethereum.crypto.blake2 import Blake2b +from ethereum.utils.ensure import ensure + +from ...vm import Evm +from ...vm.gas import GAS_BLAKE2_PER_ROUND, charge_gas +from ..exceptions import InvalidParameter + + +def blake2f(evm: Evm) -> None: + """ + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + ensure(len(data) == 213, InvalidParameter) + + blake2b = Blake2b() + rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) + + charge_gas(evm, GAS_BLAKE2_PER_ROUND * rounds) + + # OPERATION + ensure(f in [0, 1], InvalidParameter) + + evm.output = blake2b.compress(rounds, h, m, t_0, t_1, f) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..828b60ce --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..f4acfcb4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..dd7ae99f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/mapping.md @@ -0,0 +1,52 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ALT_BN128_ADD_ADDRESS, + ALT_BN128_MUL_ADDRESS, + ALT_BN128_PAIRING_CHECK_ADDRESS, + BLAKE2F_ADDRESS, + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + MODEXP_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .alt_bn128 import alt_bn128_add, alt_bn128_mul, alt_bn128_pairing_check +from .blake2f import blake2f +from .ecrecover import ecrecover +from .identity import identity +from .modexp import modexp +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, + MODEXP_ADDRESS: modexp, + ALT_BN128_ADD_ADDRESS: alt_bn128_add, + ALT_BN128_MUL_ADDRESS: alt_bn128_mul, + ALT_BN128_PAIRING_CHECK_ADDRESS: alt_bn128_pairing_check, + BLAKE2F_ADDRESS: blake2f, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/modexp.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/modexp.md new file mode 100644 index 00000000..c5bf0598 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/modexp.md @@ -0,0 +1,174 @@ +# ๐Ÿ modexp.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/precompiled_contracts/modexp.py) + +```python +""" +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +""" +from ethereum.base_types import U256, Bytes, Uint + +from ...vm import Evm +from ...vm.gas import charge_gas +from ..memory import buffer_read + +GQUADDIVISOR = 3 + + +def modexp(evm: Evm) -> None: + """ + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + """ + data = evm.message.data + + # GAS + base_length = U256.from_be_bytes(buffer_read(data, U256(0), U256(32))) + exp_length = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + modulus_length = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + + exp_start = U256(96) + base_length + + exp_head = Uint.from_be_bytes( + buffer_read(data, exp_start, min(U256(32), exp_length)) + ) + + charge_gas( + evm, + gas_cost(base_length, modulus_length, exp_length, exp_head), + ) + + # OPERATION + if base_length == 0 and modulus_length == 0: + evm.output = Bytes() + return + + base = Uint.from_be_bytes(buffer_read(data, U256(96), base_length)) + exp = Uint.from_be_bytes(buffer_read(data, exp_start, exp_length)) + + modulus_start = exp_start + exp_length + modulus = Uint.from_be_bytes( + buffer_read(data, modulus_start, modulus_length) + ) + + if modulus == 0: + evm.output = Bytes(b"\x00") * modulus_length + else: + evm.output = Uint(pow(base, exp, modulus)).to_bytes( + modulus_length, "big" + ) + + +def complexity(base_length: U256, modulus_length: U256) -> Uint: + """ + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + """ + max_length = max(Uint(base_length), Uint(modulus_length)) + words = (max_length + 7) // 8 + return words**2 + + +def iterations(exponent_length: U256, exponent_head: Uint) -> Uint: + """ + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + """ + if exponent_length <= 32 and exponent_head == 0: + count = Uint(0) + elif exponent_length <= 32: + bit_length = Uint(exponent_head.bit_length()) + + if bit_length > 0: + bit_length -= 1 + + count = bit_length + else: + length_part = 8 * (Uint(exponent_length) - 32) + bits_part = Uint(exponent_head.bit_length()) + + if bits_part > 0: + bits_part -= 1 + + count = length_part + bits_part + + return max(count, Uint(1)) + + +def gas_cost( + base_length: U256, + modulus_length: U256, + exponent_length: U256, + exponent_head: Uint, +) -> Uint: + """ + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + """ + multiplication_complexity = complexity(base_length, modulus_length) + iteration_count = iterations(exponent_length, exponent_head) + cost = multiplication_complexity * iteration_count + cost //= GQUADDIVISOR + return max(Uint(200), cost) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..5ad689fa --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..d03285d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/runtime.md new file mode 100644 index 00000000..4418203f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/shanghai/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/stack.md new file mode 100644 index 00000000..e2b24653 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/shanghai/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/shanghai/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/__init__.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/__init__.md new file mode 100644 index 00000000..17827063 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/__init__.md @@ -0,0 +1,17 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(2675000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/blocks.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/blocks.md new file mode 100644 index 00000000..d3c6d068 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import Transaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Transaction, ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + post_state: Root + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/bloom.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/bloom.md new file mode 100644 index 00000000..1d6cc247 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/fork.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/fork.md new file mode 100644 index 00000000..1381b2d2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/fork.md @@ -0,0 +1,1025 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Bytes32, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + account_exists_and_is_empty, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + Transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(5 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, + chain_id: U64, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(chain_id, tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + post_state: Bytes32, + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Receipt: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + post_state=post_state, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Transaction, ...], + ommers: Tuple[Header, ...], + chain_id: U64, +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[Bytes, Optional[Transaction]] = Trie( + secured=False, default=None + ) + receipts_trie: Trie[Bytes, Optional[Receipt]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(transactions): + trie_set(transactions_trie, rlp.encode(Uint(i)), tx) + + sender_address = check_transaction(tx, gas_available, chain_id) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + traces=[], + ) + + gas_used, logs = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, state_root(state), (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + if coinbase_balance_after_mining_fee != 0: + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + elif account_exists_and_is_empty(env.state, env.coinbase): + destroy_account(env.state, env.coinbase) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + for address in output.touched_accounts: + if account_exists_and_is_empty(env.state, address): + destroy_account(env.state, address) + + return total_gas_used, output.logs + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + return Uint(TX_BASE_COST + data_cost + create_cost) + + +def recover_sender(chain_id: U64, tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + v, r, s = tx.v, tx.r, tx.s + + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + if v == 27 or v == 28: + public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) + else: + ensure(v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock) + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + return Address(keccak256(public_key)[12:32]) + + +def signing_hash_pre155(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def signing_hash_155(tx: Transaction, chain_id: U64) -> Hash32: + """ + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + chain_id, + Uint(0), + Uint(0), + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max(1 - int(block_timestamp - parent_timestamp) // 10, -99) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = (int(block_number) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/fork_types.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/fork_types.md new file mode 100644 index 00000000..6e6d1b40 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/state.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/state.md new file mode 100644 index 00000000..f6c9d18d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/state.md @@ -0,0 +1,558 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def is_account_empty(state: State, address: Address) -> bool: + """ + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + """ + account = get_account(state, address) + return ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def account_exists_and_is_empty(state: State, address: Address) -> bool: + """ + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + """ + account = get_account_optional(state, address) + return ( + account is not None + and account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def is_account_alive(state: State, address: Address) -> bool: + """ + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + """ + account = get_account_optional(state, address) + if account is None: + return False + else: + return not ( + account.nonce == Uint(0) + and account.code == b"" + and account.balance == 0 + ) + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/transactions.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/transactions.md new file mode 100644 index 00000000..8cdaca0a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/transactions.md @@ -0,0 +1,39 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Union + +from ..base_types import U256, Bytes, Bytes0, Uint, slotted_freezable +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 68 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 + + +@slotted_freezable +@dataclass +class Transaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/trie.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/trie.md new file mode 100644 index 00000000..00866934 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.tangerine_whistle import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import Transaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, Transaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Transaction], + Optional[Receipt], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (Transaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/__init__.md new file mode 100644 index 00000000..18849431 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/address.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/address.md new file mode 100644 index 00000000..72452e76 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/address.md @@ -0,0 +1,68 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this spurious dragon version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.spurious_dragon.fork_types.Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/hexadecimal.md new file mode 100644 index 00000000..33940fe6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/utils/hexadecimal.py) + +```python +""" +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. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/message.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/message.md new file mode 100644 index 00000000..01b3d04c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/utils/message.md @@ -0,0 +1,98 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/utils/message.py) + +```python +""" +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. +""" +from typing import Optional, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.spurious_dragon.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/__init__.md new file mode 100644 index 00000000..c0a10e5d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/__init__.md @@ -0,0 +1,142 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State, account_exists_and_is_empty +from .precompiled_contracts import RIPEMD160_ADDRESS + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: U256 + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + touched_accounts: Set[Address] + error: Optional[Exception] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + evm.touched_accounts.update(child_evm.touched_accounts) + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(child_evm.message.current_target) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was + # cleared despite running out of gas. This is an obscure edge case that can + # only happen to a precompile. + # According to the general rules governing clearing of empty accounts, the + # touch should have been reverted. Due to client bugs, this event went + # unnoticed and 0x3 has been exempted from the rule that touches are + # reverted in order to preserve this historical behaviour. + if RIPEMD160_ADDRESS in child_evm.touched_accounts: + evm.touched_accounts.add(RIPEMD160_ADDRESS) + if child_evm.message.current_target == RIPEMD160_ADDRESS: + if account_exists_and_is_empty( + evm.env.state, child_evm.message.current_target + ): + evm.touched_accounts.add(RIPEMD160_ADDRESS) + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/exceptions.md new file mode 100644 index 00000000..83f632df --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/exceptions.md @@ -0,0 +1,93 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/gas.md new file mode 100644 index 00000000..3a584b06 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/gas.md @@ -0,0 +1,244 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_SLOAD = Uint(200) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(50) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_EXTERNAL = Uint(700) +GAS_BALANCE = Uint(400) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_CALL = Uint(700) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/__init__.md new file mode 100644 index 00000000..da441306 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/__init__.md @@ -0,0 +1,336 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + SELFDESTRUCT = 0xFF + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/arithmetic.md new file mode 100644 index 00000000..49909aca --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/bitwise.md new file mode 100644 index 00000000..f6f8454c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/bitwise.md @@ -0,0 +1,160 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/block.md new file mode 100644 index 00000000..cfb25eaf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/block.md @@ -0,0 +1,189 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/comparison.md new file mode 100644 index 00000000..ec81fdeb --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/control_flow.md new file mode 100644 index 00000000..f81dec98 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/environment.md new file mode 100644 index 00000000..0cfde1d0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/environment.md @@ -0,0 +1,381 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.utils.numeric import ceil32 + +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..gas import ( + GAS_BALANCE, + GAS_BASE, + GAS_COPY, + GAS_EXTERNAL, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_BALANCE) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_EXTERNAL) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/keccak.md new file mode 100644 index 00000000..a591ab53 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/log.md new file mode 100644 index 00000000..d6fd1c65 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/log.md @@ -0,0 +1,91 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 + +from ...blocks import Log +from .. import Evm +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/memory.md new file mode 100644 index 00000000..a8429ee1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/stack.md new file mode 100644 index 00000000..70da8498 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/storage.md new file mode 100644 index 00000000..7f0f216d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/storage.md @@ -0,0 +1,89 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" + +from ...state import get_storage, set_storage +from .. import Evm +from ..gas import ( + GAS_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + current_value = get_storage(evm.env.state, evm.message.current_target, key) + if new_value != 0 and current_value == 0: + gas_cost = GAS_STORAGE_SET + else: + gas_cost = GAS_STORAGE_UPDATE + + if new_value == 0 and current_value != 0: + evm.refund_counter += GAS_STORAGE_CLEAR_REFUND + + charge_gas(evm, gas_cost) + + # OPERATION + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/system.md new file mode 100644 index 00000000..c869989c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/instructions/system.md @@ -0,0 +1,468 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint + +from ...fork_types import Address +from ...state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + get_account, + increment_nonce, + is_account_alive, + set_account_balance, +) +from ...utils.address import compute_contract_address, to_address +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..gas import ( + GAS_CALL, + GAS_CALL_VALUE, + GAS_CREATE, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + push(evm.stack, U256(0)) + evm.gas_left += create_message_gas + elif account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + else: + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push( + evm.stack, U256.from_be_bytes(child_evm.message.current_target) + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + create_gas_cost = ( + Uint(0) + if value == 0 or is_account_alive(evm.env.state, to) + else GAS_NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if ( + not is_account_alive(evm.env.state, beneficiary) + and get_account(evm.env.state, evm.message.current_target).balance != 0 + ): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # mark beneficiary as touched + if account_exists_and_is_empty(evm.env.state, beneficiary): + evm.touched_accounts.add(beneficiary) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/interpreter.md new file mode 100644 index 00000000..e4db8454 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/interpreter.md @@ -0,0 +1,295 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Iterable, Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) +from ethereum.utils.ensure import ensure + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_exists_and_is_empty, + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + increment_nonce, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + OutOfGasError, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) +MAX_CODE_SIZE = 0x6000 + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `touched_accounts`: Accounts that have been touched. + 6. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + touched_accounts: Iterable[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + if account_exists_and_is_empty(env.state, Address(message.target)): + evm.touched_accounts.add(Address(message.target)) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + touched_accounts = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + touched_accounts = evm.touched_accounts + refund_counter = evm.refund_counter + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + touched_accounts=touched_accounts, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.spurious_dragon.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by two `CREATE` calls collide. + # * The first `CREATE` happened before Spurious Dragon and left empty + # code. + destroy_storage(env.state, message.current_target) + + increment_nonce(env.state, message.current_target) + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + ensure(len(contract_code) <= MAX_CODE_SIZE, OutOfGasError) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.spurious_dragon.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=U256(0), + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + touched_accounts=set(), + error=None, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/memory.md new file mode 100644 index 00000000..2cae3169 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..ecdfdf9d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/__init__.md @@ -0,0 +1,34 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..7356c56e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..4f34ad00 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..b2d99f00 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/mapping.md @@ -0,0 +1,39 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .ecrecover import ecrecover +from .identity import identity +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..5082a290 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..1e702ed1 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/runtime.md new file mode 100644 index 00000000..0fbbaf93 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/stack.md new file mode 100644 index 00000000..17e9af27 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/spurious_dragon/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/spurious_dragon/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/__init__.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/__init__.md new file mode 100644 index 00000000..5f4972ba --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/__init__.md @@ -0,0 +1,16 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/__init__.py) + +```python +""" +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. +""" + +from ethereum.fork_criteria import ByBlockNumber + +FORK_CRITERIA = ByBlockNumber(2463000) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/blocks.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/blocks.md new file mode 100644 index 00000000..de5f1dea --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/blocks.md @@ -0,0 +1,84 @@ +# ๐Ÿ blocks.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/blocks.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Tuple + +from ..base_types import U256, Bytes, Bytes8, Bytes32, Uint, slotted_freezable +from ..crypto.hash import Hash32 +from .fork_types import Address, Bloom, Root +from .transactions import Transaction + + +@slotted_freezable +@dataclass +class Header: + """ + Header portion of a block on the chain. + """ + + parent_hash: Hash32 + ommers_hash: Hash32 + coinbase: Address + state_root: Root + transactions_root: Root + receipt_root: Root + bloom: Bloom + difficulty: Uint + number: Uint + gas_limit: Uint + gas_used: Uint + timestamp: U256 + extra_data: Bytes + mix_digest: Bytes32 + nonce: Bytes8 + + +@slotted_freezable +@dataclass +class Block: + """ + A complete block. + """ + + header: Header + transactions: Tuple[Transaction, ...] + ommers: Tuple[Header, ...] + + +@slotted_freezable +@dataclass +class Log: + """ + Data record produced during the execution of a transaction. + """ + + address: Address + topics: Tuple[Hash32, ...] + data: bytes + + +@slotted_freezable +@dataclass +class Receipt: + """ + Result of a transaction. + """ + + post_state: Root + cumulative_gas_used: Uint + bloom: Bloom + logs: Tuple[Log, ...] +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/bloom.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/bloom.md new file mode 100644 index 00000000..dfdcbb2a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/bloom.md @@ -0,0 +1,90 @@ +# ๐Ÿ bloom.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/bloom.py) + +```python +""" +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. +""" + +from typing import Tuple + +from ethereum.base_types import Uint +from ethereum.crypto.hash import keccak256 + +from .blocks import Log +from .fork_types import Bloom + + +def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None: + """ + 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. + """ + hash = keccak256(bloom_entry) + + for idx in (0, 2, 4): + # Obtain the least significant 11 bits from the pair of bytes + # (16 bits), and set this bit in bloom bytearray. + # The obtained bit is 0-indexed in the bloom filter from the least + # significant bit to the most significant bit. + bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF + # Below is the index of the bit in the bytearray (where 0-indexed + # byte is the most significant byte) + bit_index = 0x07FF - bit_to_set + + byte_index = bit_index // 8 + bit_value = 1 << (7 - (bit_index % 8)) + bloom[byte_index] = bloom[byte_index] | bit_value + + +def logs_bloom(logs: Tuple[Log, ...]) -> Bloom: + """ + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + """ + bloom: bytearray = bytearray(b"\x00" * 256) + + for log in logs: + add_to_bloom(bloom, log.address) + for topic in log.topics: + add_to_bloom(bloom, topic) + + return Bloom(bloom) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/fork.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/fork.md new file mode 100644 index 00000000..f6f259e0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/fork.md @@ -0,0 +1,977 @@ +# ๐Ÿ fork.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/fork.py) + +```python +""" +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple + +from ethereum.base_types import Bytes0 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.ethash import dataset_size, generate_cache, hashimoto_light +from ethereum.exceptions import InvalidBlock +from ethereum.utils.ensure import ensure + +from .. import rlp +from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Bytes32, Uint +from . import vm +from .blocks import Block, Header, Log, Receipt +from .bloom import logs_bloom +from .fork_types import Address, Bloom, Root +from .state import ( + State, + create_ether, + destroy_account, + get_account, + increment_nonce, + set_account_balance, + state_root, +) +from .transactions import ( + TX_BASE_COST, + TX_CREATE_COST, + TX_DATA_COST_PER_NON_ZERO, + TX_DATA_COST_PER_ZERO, + Transaction, +) +from .trie import Trie, root, trie_set +from .utils.message import prepare_message +from .vm.interpreter import process_message_call + +BLOCK_REWARD = U256(5 * 10**18) +GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 +GAS_LIMIT_MINIMUM = 5000 +MINIMUM_DIFFICULTY = Uint(131072) +MAX_OMMER_DEPTH = 6 + + +@dataclass +class BlockChain: + """ + History and current state of the block chain. + """ + + blocks: List[Block] + state: State + chain_id: U64 + + +def apply_fork(old: BlockChain) -> BlockChain: + """ + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + """ + return old + + +def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: + """ + 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. + """ + recent_blocks = chain.blocks[-255:] + # TODO: This function has not been tested rigorously + if len(recent_blocks) == 0: + return [] + + recent_block_hashes = [] + + for block in recent_blocks: + prev_block_hash = block.header.parent_hash + recent_block_hashes.append(prev_block_hash) + + # We are computing the hash only for the most recent block and not for + # the rest of the blocks as they have successors which have the hash of + # the current block as parent hash. + most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) + recent_block_hashes.append(most_recent_block_hash) + + return recent_block_hashes + + +def state_transition(chain: BlockChain, block: Block) -> None: + """ + 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`. + """ + parent_header = chain.blocks[-1].header + validate_header(block.header, parent_header) + validate_ommers(block.ommers, block.header, chain) + 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, + ) + ensure( + apply_body_output.block_gas_used == block.header.gas_used, InvalidBlock + ) + ensure( + apply_body_output.transactions_root == block.header.transactions_root, + InvalidBlock, + ) + ensure( + apply_body_output.state_root == block.header.state_root, InvalidBlock + ) + ensure( + apply_body_output.receipt_root == block.header.receipt_root, + InvalidBlock, + ) + ensure( + apply_body_output.block_logs_bloom == block.header.bloom, InvalidBlock + ) + + chain.blocks.append(block) + if len(chain.blocks) > 255: + # Real clients have to store more blocks to deal with reorgs, but the + # protocol only requires the last 255 + chain.blocks = chain.blocks[-255:] + + +def validate_header(header: Header, parent_header: Header) -> None: + """ + 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 + """ + ensure(header.timestamp > parent_header.timestamp, InvalidBlock) + ensure(header.number == parent_header.number + 1, InvalidBlock) + ensure( + check_gas_limit(header.gas_limit, parent_header.gas_limit), + InvalidBlock, + ) + ensure(len(header.extra_data) <= 32, InvalidBlock) + + block_difficulty = calculate_block_difficulty( + header.number, + header.timestamp, + parent_header.timestamp, + parent_header.difficulty, + ) + ensure(header.difficulty == block_difficulty, InvalidBlock) + + block_parent_hash = keccak256(rlp.encode(parent_header)) + ensure(header.parent_hash == block_parent_hash, InvalidBlock) + + validate_proof_of_work(header) + + +def generate_header_hash_for_pow(header: Header) -> Hash32: + """ + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + """ + header_data_without_pow_artefacts = [ + header.parent_hash, + header.ommers_hash, + header.coinbase, + header.state_root, + header.transactions_root, + header.receipt_root, + header.bloom, + header.difficulty, + header.number, + header.gas_limit, + header.gas_used, + header.timestamp, + header.extra_data, + ] + + return rlp.rlp_hash(header_data_without_pow_artefacts) + + +def validate_proof_of_work(header: Header) -> None: + """ + 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. + """ + header_hash = generate_header_hash_for_pow(header) + # TODO: Memoize this somewhere and read from that data instead of + # calculating cache for every block validation. + cache = generate_cache(header.number) + mix_digest, result = hashimoto_light( + header_hash, header.nonce, cache, dataset_size(header.number) + ) + + ensure(mix_digest == header.mix_digest, InvalidBlock) + ensure( + Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), + InvalidBlock, + ) + + +def check_transaction( + tx: Transaction, + gas_available: Uint, +) -> Address: + """ + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + """ + ensure(tx.gas <= gas_available, InvalidBlock) + sender_address = recover_sender(tx) + + return sender_address + + +def make_receipt( + tx: Transaction, + post_state: Bytes32, + cumulative_gas_used: Uint, + logs: Tuple[Log, ...], +) -> Receipt: + """ + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + """ + receipt = Receipt( + post_state=post_state, + cumulative_gas_used=cumulative_gas_used, + bloom=logs_bloom(logs), + logs=logs, + ) + + return receipt + + +@dataclass +class ApplyBodyOutput: + """ + Output from applying the block body to the present state. + + Contains the following: + + block_gas_used : `ethereum.base_types.Uint` + Gas used for executing all transactions. + transactions_root : `ethereum.fork_types.Root` + Trie root of all the transactions in the block. + receipt_root : `ethereum.fork_types.Root` + Trie root of all the receipts in the block. + block_logs_bloom : `Bloom` + Logs bloom of all the logs included in all the transactions of the + block. + state_root : `ethereum.fork_types.Root` + State root after all transactions have been executed. + """ + + block_gas_used: Uint + transactions_root: Root + receipt_root: Root + block_logs_bloom: Bloom + state_root: Root + + +def apply_body( + state: State, + block_hashes: List[Hash32], + coinbase: Address, + block_number: Uint, + block_gas_limit: Uint, + block_time: U256, + block_difficulty: Uint, + transactions: Tuple[Transaction, ...], + ommers: Tuple[Header, ...], +) -> ApplyBodyOutput: + """ + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + """ + gas_available = block_gas_limit + transactions_trie: Trie[Bytes, Optional[Transaction]] = Trie( + secured=False, default=None + ) + receipts_trie: Trie[Bytes, Optional[Receipt]] = Trie( + secured=False, default=None + ) + block_logs: Tuple[Log, ...] = () + + for i, tx in enumerate(transactions): + trie_set(transactions_trie, rlp.encode(Uint(i)), tx) + + sender_address = check_transaction(tx, gas_available) + + env = vm.Environment( + caller=sender_address, + origin=sender_address, + block_hashes=block_hashes, + coinbase=coinbase, + number=block_number, + gas_limit=block_gas_limit, + gas_price=tx.gas_price, + time=block_time, + difficulty=block_difficulty, + state=state, + traces=[], + ) + + gas_used, logs = process_transaction(env, tx) + gas_available -= gas_used + + receipt = make_receipt( + tx, state_root(state), (block_gas_limit - gas_available), logs + ) + + trie_set( + receipts_trie, + rlp.encode(Uint(i)), + receipt, + ) + + block_logs += logs + + pay_rewards(state, block_number, coinbase, ommers) + + block_gas_used = block_gas_limit - gas_available + + block_logs_bloom = logs_bloom(block_logs) + + return ApplyBodyOutput( + block_gas_used, + root(transactions_trie), + root(receipts_trie), + block_logs_bloom, + state_root(state), + ) + + +def validate_ommers( + ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain +) -> None: + """ + 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. + """ + block_hash = rlp.rlp_hash(block_header) + + ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) + + if len(ommers) == 0: + # Nothing to validate + return + + # Check that each ommer satisfies the constraints of a header + for ommer in ommers: + ensure(1 <= ommer.number < block_header.number, InvalidBlock) + ommer_parent_header = chain.blocks[ + -(block_header.number - ommer.number) - 1 + ].header + validate_header(ommer, ommer_parent_header) + + # Check that there can be only at most 2 ommers for a block. + ensure(len(ommers) <= 2, InvalidBlock) + + ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] + # Check that there are no duplicates in the ommers of current block + ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) + + recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] + recent_canonical_block_hashes = { + rlp.rlp_hash(block.header) for block in recent_canonical_blocks + } + recent_ommers_hashes: Set[Hash32] = set() + for block in recent_canonical_blocks: + recent_ommers_hashes = recent_ommers_hashes.union( + {rlp.rlp_hash(ommer) for ommer in block.ommers} + ) + + for ommer_index, ommer in enumerate(ommers): + ommer_hash = ommers_hashes[ommer_index] + # The current block shouldn't be the ommer + ensure(ommer_hash != block_hash, InvalidBlock) + + # Ommer shouldn't be one of the recent canonical blocks + ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) + + # Ommer shouldn't be one of the uncles mentioned in the recent + # canonical blocks + ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) + + # Ommer age with respect to the current block. For example, an age of + # 1 indicates that the ommer is a sibling of previous block. + ommer_age = block_header.number - ommer.number + ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) + + ensure( + ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock + ) + ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) + + +def pay_rewards( + state: State, + block_number: Uint, + coinbase: Address, + ommers: Tuple[Header, ...], +) -> None: + """ + 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. + """ + miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) + create_ether(state, coinbase, miner_reward) + + for ommer in ommers: + # Ommer age with respect to the current block. + ommer_age = U256(block_number - ommer.number) + ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 + create_ether(state, ommer.coinbase, ommer_miner_reward) + + +def process_transaction( + env: vm.Environment, tx: Transaction +) -> Tuple[Uint, Tuple[Log, ...]]: + """ + 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. + """ + ensure(validate_transaction(tx), InvalidBlock) + + sender = env.origin + sender_account = get_account(env.state, sender) + gas_fee = tx.gas * tx.gas_price + ensure(sender_account.nonce == tx.nonce, InvalidBlock) + ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock) + ensure(sender_account.code == bytearray(), InvalidBlock) + + gas = tx.gas - calculate_intrinsic_cost(tx) + increment_nonce(env.state, sender) + sender_balance_after_gas_fee = sender_account.balance - gas_fee + set_account_balance(env.state, sender, sender_balance_after_gas_fee) + + message = prepare_message( + sender, + tx.to, + tx.value, + tx.data, + gas, + env, + ) + + output = process_message_call(message, env) + + gas_used = tx.gas - output.gas_left + gas_refund = min(gas_used // 2, output.refund_counter) + gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price + transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price + total_gas_used = gas_used - gas_refund + + # refund gas + sender_balance_after_refund = ( + get_account(env.state, sender).balance + gas_refund_amount + ) + set_account_balance(env.state, sender, sender_balance_after_refund) + + # transfer miner fees + coinbase_balance_after_mining_fee = ( + get_account(env.state, env.coinbase).balance + transaction_fee + ) + set_account_balance( + env.state, env.coinbase, coinbase_balance_after_mining_fee + ) + + for address in output.accounts_to_delete: + destroy_account(env.state, address) + + return total_gas_used, output.logs + + +def validate_transaction(tx: Transaction) -> bool: + """ + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + """ + return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 + + +def calculate_intrinsic_cost(tx: Transaction) -> Uint: + """ + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + """ + data_cost = 0 + + for byte in tx.data: + if byte == 0: + data_cost += TX_DATA_COST_PER_ZERO + else: + data_cost += TX_DATA_COST_PER_NON_ZERO + + if tx.to == Bytes0(b""): + create_cost = TX_CREATE_COST + else: + create_cost = 0 + + return Uint(TX_BASE_COST + data_cost + create_cost) + + +def recover_sender(tx: Transaction) -> Address: + """ + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + """ + v, r, s = tx.v, tx.r, tx.s + + # if v > 28: + # v = v - (chain_id*2+8) + + ensure(v == 27 or v == 28, InvalidBlock) + ensure(0 < r and r < SECP256K1N, InvalidBlock) + ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) + + public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + return Address(keccak256(public_key)[12:32]) + + +def signing_hash(tx: Transaction) -> Hash32: + """ + Compute the hash of a transaction used in the signature. + + The values that are used to compute the signing hash set the rules for a + transaction. For example, signing over the gas sets a limit for the + amount of money that is allowed to be pulled out of the sender's account. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + """ + return keccak256( + rlp.encode( + ( + tx.nonce, + tx.gas_price, + tx.gas, + tx.to, + tx.value, + tx.data, + ) + ) + ) + + +def compute_header_hash(header: Header) -> Hash32: + """ + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + """ + return keccak256(rlp.encode(header)) + + +def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: + """ + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + """ + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + if gas_limit >= parent_gas_limit + max_adjustment_delta: + return False + if gas_limit <= parent_gas_limit - max_adjustment_delta: + return False + if gas_limit < GAS_LIMIT_MINIMUM: + return False + + return True + + +def calculate_block_difficulty( + block_number: Uint, + block_timestamp: U256, + parent_timestamp: U256, + parent_difficulty: Uint, +) -> Uint: + """ + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + """ + offset = ( + int(parent_difficulty) + // 2048 + * max(1 - int(block_timestamp - parent_timestamp) // 10, -99) + ) + difficulty = int(parent_difficulty) + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the + # start of Frontier, but was added shortly after launch. However since the + # bomb has no effect prior to block 200000 we pretend it existed from + # genesis. + # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = (int(block_number) // 100000) - 2 + if num_bomb_periods >= 0: + difficulty += 2**num_bomb_periods + + # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding + # the bomb. This bug does not matter because the difficulty is always much + # greater than `MINIMUM_DIFFICULTY` on Mainnet. + return Uint(max(difficulty, MINIMUM_DIFFICULTY)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/fork_types.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/fork_types.md new file mode 100644 index 00000000..25dcd92e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/fork_types.md @@ -0,0 +1,73 @@ +# ๐Ÿ fork_types.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/fork_types.py) + +```python +""" +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +""" + +from dataclasses import dataclass + +from .. import rlp +from ..base_types import ( + U256, + Bytes, + Bytes20, + Bytes256, + Uint, + slotted_freezable, +) +from ..crypto.hash import Hash32, keccak256 + +Address = Bytes20 +Root = Hash32 + +Bloom = Bytes256 + + +@slotted_freezable +@dataclass +class Account: + """ + State associated with an address. + """ + + nonce: Uint + balance: U256 + code: bytes + + +EMPTY_ACCOUNT = Account( + nonce=Uint(0), + balance=U256(0), + code=bytearray(), +) + + +def encode_account(raw_account_data: Account, storage_root: Bytes) -> Bytes: + """ + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + """ + return rlp.encode( + ( + raw_account_data.nonce, + raw_account_data.balance, + storage_root, + keccak256(raw_account_data.code), + ) + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/state.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/state.md new file mode 100644 index 00000000..ed211379 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/state.md @@ -0,0 +1,479 @@ +# ๐Ÿ state.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/state.py) + +```python +""" +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`. +""" +from dataclasses import dataclass, field +from typing import Callable, Dict, List, Optional, Tuple + +from ethereum.base_types import U256, Bytes, Uint, modify +from ethereum.utils.ensure import ensure + +from .fork_types import EMPTY_ACCOUNT, Account, Address, Root +from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set + + +@dataclass +class State: + """ + Contains all information that is preserved between transactions. + """ + + _main_trie: Trie[Address, Optional[Account]] = field( + default_factory=lambda: Trie(secured=True, default=None) + ) + _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( + default_factory=dict + ) + _snapshots: List[ + Tuple[ + Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] + ] + ] = field(default_factory=list) + + +def close_state(state: State) -> None: + """ + Free resources held by the state. Used by optimized implementations to + release file descriptors. + """ + del state._main_trie + del state._storage_tries + del state._snapshots + + +def begin_transaction(state: State) -> None: + """ + 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. + """ + state._snapshots.append( + ( + copy_trie(state._main_trie), + {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, + ) + ) + + +def commit_transaction(state: State) -> None: + """ + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + """ + state._snapshots.pop() + + +def rollback_transaction(state: State) -> None: + """ + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + """ + state._main_trie, state._storage_tries = state._snapshots.pop() + + +def get_account(state: State, address: Address) -> Account: + """ + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + """ + account = get_account_optional(state, address) + if isinstance(account, Account): + return account + else: + return EMPTY_ACCOUNT + + +def get_account_optional(state: State, address: Address) -> Optional[Account]: + """ + 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. + """ + account = trie_get(state._main_trie, address) + return account + + +def set_account( + state: State, address: Address, account: Optional[Account] +) -> None: + """ + 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. + """ + trie_set(state._main_trie, address, account) + + +def destroy_account(state: State, address: Address) -> None: + """ + 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. + """ + destroy_storage(state, address) + set_account(state, address, None) + + +def destroy_storage(state: State, address: Address) -> None: + """ + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + """ + if address in state._storage_tries: + del state._storage_tries[address] + + +def get_storage(state: State, address: Address, key: Bytes) -> U256: + """ + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + """ + trie = state._storage_tries.get(address) + if trie is None: + return U256(0) + + value = trie_get(trie, key) + + assert isinstance(value, U256) + return value + + +def set_storage( + state: State, address: Address, key: Bytes, value: U256 +) -> None: + """ + 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. + """ + assert trie_get(state._main_trie, address) is not None + + trie = state._storage_tries.get(address) + if trie is None: + trie = Trie(secured=True, default=U256(0)) + state._storage_tries[address] = trie + trie_set(trie, key, value) + if trie._data == {}: + del state._storage_tries[address] + + +def storage_root(state: State, address: Address) -> Root: + """ + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + """ + assert not state._snapshots + if address in state._storage_tries: + return root(state._storage_tries[address]) + else: + return EMPTY_TRIE_ROOT + + +def state_root(state: State) -> Root: + """ + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + """ + assert not state._snapshots + + def get_storage_root(address: Address) -> Root: + return storage_root(state, address) + + return root(state._main_trie, get_storage_root=get_storage_root) + + +def account_exists(state: State, address: Address) -> bool: + """ + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + """ + return get_account_optional(state, address) is not None + + +def account_has_code_or_nonce(state: State, address: Address) -> bool: + """ + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + """ + account = get_account(state, address) + return account.nonce != Uint(0) or account.code != b"" + + +def modify_state( + state: State, address: Address, f: Callable[[Account], None] +) -> None: + """ + Modify an `Account` in the `State`. + """ + set_account(state, address, modify(get_account(state, address), f)) + + +def move_ether( + state: State, + sender_address: Address, + recipient_address: Address, + amount: U256, +) -> None: + """ + Move funds between accounts. + """ + + def reduce_sender_balance(sender: Account) -> None: + ensure(sender.balance >= amount, AssertionError) + sender.balance -= amount + + def increase_recipient_balance(recipient: Account) -> None: + recipient.balance += amount + + modify_state(state, sender_address, reduce_sender_balance) + modify_state(state, recipient_address, increase_recipient_balance) + + +def set_account_balance(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def set_balance(account: Account) -> None: + account.balance = amount + + modify_state(state, address, set_balance) + + +def touch_account(state: State, address: Address) -> None: + """ + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + """ + if not account_exists(state, address): + set_account(state, address, EMPTY_ACCOUNT) + + +def increment_nonce(state: State, address: Address) -> None: + """ + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + """ + + def increase_nonce(sender: Account) -> None: + sender.nonce += 1 + + modify_state(state, address, increase_nonce) + + +def set_code(state: State, address: Address, code: Bytes) -> None: + """ + 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. + """ + + def write_code(sender: Account) -> None: + sender.code = code + + modify_state(state, address, write_code) + + +def create_ether(state: State, address: Address, amount: U256) -> None: + """ + 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. + """ + + def increase_balance(account: Account) -> None: + account.balance += amount + + modify_state(state, address, increase_balance) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/transactions.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/transactions.md new file mode 100644 index 00000000..5ab69d76 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/transactions.md @@ -0,0 +1,39 @@ +# ๐Ÿ transactions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/transactions.py) + +```python +""" +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. +""" +from dataclasses import dataclass +from typing import Union + +from ..base_types import U256, Bytes, Bytes0, Uint, slotted_freezable +from .fork_types import Address + +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 68 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 + + +@slotted_freezable +@dataclass +class Transaction: + """ + Atomic operation performed on the block chain. + """ + + nonce: U256 + gas_price: Uint + gas: Uint + to: Union[Bytes0, Address] + value: U256 + data: Bytes + v: U256 + r: U256 + s: U256 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/trie.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/trie.md new file mode 100644 index 00000000..7ad00550 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/trie.md @@ -0,0 +1,470 @@ +# ๐Ÿ trie.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/trie.py) + +```python +""" +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +""" + +import copy +from dataclasses import dataclass, field +from typing import ( + Callable, + Dict, + Generic, + List, + Mapping, + MutableMapping, + Optional, + Sequence, + TypeVar, + Union, + cast, +) + +from ethereum.crypto.hash import keccak256 +from ethereum.dao_fork import trie as previous_trie +from ethereum.utils.ensure import ensure +from ethereum.utils.hexadecimal import hex_to_bytes + +from .. import rlp +from ..base_types import U256, Bytes, Uint, slotted_freezable +from .blocks import Receipt +from .fork_types import Account, Address, Root, encode_account +from .transactions import Transaction + +# note: an empty trie (regardless of whether it is secured) has root: +# +# keccak256(RLP(b'')) +# == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 +# +# also: +# +# keccak256(RLP(())) +# == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 +# +# which is the sha3Uncles hash in block header with no uncles +EMPTY_TRIE_ROOT = Root( + hex_to_bytes( + "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ) +) + +Node = Union[Account, Bytes, Transaction, Receipt, Uint, U256, None] +K = TypeVar("K", bound=Bytes) +V = TypeVar( + "V", + Optional[Account], + Optional[Bytes], + Bytes, + Optional[Transaction], + Optional[Receipt], + Uint, + U256, +) + + +@slotted_freezable +@dataclass +class LeafNode: + """Leaf node in the Merkle Trie""" + + rest_of_key: Bytes + value: rlp.RLP + + +@slotted_freezable +@dataclass +class ExtensionNode: + """Extension node in the Merkle Trie""" + + key_segment: Bytes + subnode: rlp.RLP + + +@slotted_freezable +@dataclass +class BranchNode: + """Branch node in the Merkle Trie""" + + subnodes: List[rlp.RLP] + value: rlp.RLP + + +InternalNode = Union[LeafNode, ExtensionNode, BranchNode] + + +def encode_internal_node(node: Optional[InternalNode]) -> rlp.RLP: + """ + 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. + """ + unencoded: rlp.RLP + if node is None: + unencoded = b"" + elif isinstance(node, LeafNode): + unencoded = ( + nibble_list_to_compact(node.rest_of_key, True), + node.value, + ) + elif isinstance(node, ExtensionNode): + unencoded = ( + nibble_list_to_compact(node.key_segment, False), + node.subnode, + ) + elif isinstance(node, BranchNode): + unencoded = node.subnodes + [node.value] + else: + raise AssertionError(f"Invalid internal node type {type(node)}!") + + encoded = rlp.encode(unencoded) + if len(encoded) < 32: + return unencoded + else: + return keccak256(encoded) + + +def encode_node(node: Node, storage_root: Optional[Bytes] = None) -> Bytes: + """ + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + """ + if isinstance(node, Account): + assert storage_root is not None + return encode_account(node, storage_root) + elif isinstance(node, (Transaction, Receipt, U256)): + return rlp.encode(cast(rlp.RLP, node)) + elif isinstance(node, Bytes): + return node + else: + return previous_trie.encode_node(node, storage_root) + + +@dataclass +class Trie(Generic[K, V]): + """ + The Merkle Trie. + """ + + secured: bool + default: V + _data: Dict[K, V] = field(default_factory=dict) + + +def copy_trie(trie: Trie[K, V]) -> Trie[K, V]: + """ + 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. + """ + return Trie(trie.secured, trie.default, copy.copy(trie._data)) + + +def trie_set(trie: Trie[K, V], key: K, value: V) -> None: + """ + 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`. + """ + if value == trie.default: + if key in trie._data: + del trie._data[key] + else: + trie._data[key] = value + + +def trie_get(trie: Trie[K, V], key: K) -> V: + """ + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + """ + return trie._data.get(key, trie.default) + + +def common_prefix_length(a: Sequence, b: Sequence) -> int: + """ + Find the longest common prefix of two sequences. + """ + for i in range(len(a)): + if i >= len(b) or a[i] != b[i]: + return i + return len(a) + + +def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: + """ + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + """ + compact = bytearray() + + if len(x) % 2 == 0: # ie even length + compact.append(16 * (2 * is_leaf)) + for i in range(0, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + else: + compact.append(16 * ((2 * is_leaf) + 1) + x[0]) + for i in range(1, len(x), 2): + compact.append(16 * x[i] + x[i + 1]) + + return Bytes(compact) + + +def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: + """ + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + """ + nibble_list = bytearray(2 * len(bytes_)) + for byte_index, byte in enumerate(bytes_): + nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 + nibble_list[byte_index * 2 + 1] = byte & 0x0F + return Bytes(nibble_list) + + +def _prepare_trie( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Mapping[Bytes, Bytes]: + """ + 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. + """ + mapped: MutableMapping[Bytes, Bytes] = {} + + for preimage, value in trie._data.items(): + if isinstance(value, Account): + assert get_storage_root is not None + address = Address(preimage) + encoded_value = encode_node(value, get_storage_root(address)) + else: + encoded_value = encode_node(value) + # Empty values are represented by their absence + ensure(encoded_value != b"", AssertionError) + key: Bytes + if trie.secured: + # "secure" tries hash keys once before construction + key = keccak256(preimage) + else: + key = preimage + mapped[bytes_to_nibble_list(key)] = encoded_value + + return mapped + + +def root( + trie: Trie[K, V], + get_storage_root: Optional[Callable[[Address], Root]] = None, +) -> Root: + """ + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + """ + obj = _prepare_trie(trie, get_storage_root) + + root_node = encode_internal_node(patricialize(obj, Uint(0))) + if len(rlp.encode(root_node)) < 32: + return keccak256(rlp.encode(root_node)) + else: + assert isinstance(root_node, Bytes) + return Root(root_node) + + +def patricialize( + obj: Mapping[Bytes, Bytes], level: Uint +) -> Optional[InternalNode]: + """ + 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`. + """ + if len(obj) == 0: + return None + + arbitrary_key = next(iter(obj)) + + # if leaf node + if len(obj) == 1: + leaf = LeafNode(arbitrary_key[level:], obj[arbitrary_key]) + return leaf + + # prepare for extension node check by finding max j such that all keys in + # obj have the same key[i:j] + substring = arbitrary_key[level:] + prefix_length = len(substring) + for key in obj: + prefix_length = min( + prefix_length, common_prefix_length(substring, key[level:]) + ) + + # finished searching, found another key at the current level + if prefix_length == 0: + break + + # if extension node + if prefix_length > 0: + prefix = arbitrary_key[level : level + prefix_length] + return ExtensionNode( + prefix, + encode_internal_node(patricialize(obj, level + prefix_length)), + ) + + branches: List[MutableMapping[Bytes, Bytes]] = [] + for _ in range(16): + branches.append({}) + value = b"" + for key in obj: + if len(key) == level: + # shouldn't ever have an account or receipt in an internal node + if isinstance(obj[key], (Account, Receipt, Uint)): + raise AssertionError + value = obj[key] + else: + branches[key[level]][key] = obj[key] + + return BranchNode( + [ + encode_internal_node(patricialize(branches[k], level + 1)) + for k in range(16) + ], + value, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/__init__.md new file mode 100644 index 00000000..7e914104 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/utils/__init__.py) + +```python +""" +Utility functions unique to this particular fork. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/address.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/address.md new file mode 100644 index 00000000..cdf77edd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/address.md @@ -0,0 +1,68 @@ +# ๐Ÿ address.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/utils/address.py) + +```python +""" +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this tangerine whistle version of +specification. +""" +from typing import Union + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ... import rlp +from ..fork_types import Address + + +def to_address(data: Union[Uint, U256]) -> Address: + """ + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + """ + return Address(data.to_be_bytes32()[-20:]) + + +def compute_contract_address(address: Address, nonce: Uint) -> Address: + """ + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.tangerine_whistle.fork_types.Address` + The computed address of the new account. + """ + computed_address = keccak256(rlp.encode([address, nonce])) + canonical_address = computed_address[-20:] + padded_address = left_pad_zero_bytes(canonical_address, 20) + return Address(padded_address) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/hexadecimal.md new file mode 100644 index 00000000..a0f978d6 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/hexadecimal.md @@ -0,0 +1,74 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/utils/hexadecimal.py) + +```python +""" +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. +""" +from ethereum.utils.hexadecimal import remove_hex_prefix + +from ..fork_types import Address, Bloom, Root + + +def hex_to_root(hex_string: str) -> Root: + """ + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + """ + return Root(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_bloom(hex_string: str) -> Bloom: + """ + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + """ + return Bloom(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_address(hex_string: str) -> Address: + """ + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + """ + return Address(bytes.fromhex(remove_hex_prefix(hex_string).rjust(40, "0"))) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/message.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/message.md new file mode 100644 index 00000000..8c693191 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/utils/message.md @@ -0,0 +1,98 @@ +# ๐Ÿ message.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/utils/message.py) + +```python +""" +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. +""" +from typing import Optional, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint + +from ..fork_types import Address +from ..state import get_account +from ..vm import Environment, Message +from .address import compute_contract_address + + +def prepare_message( + caller: Address, + target: Union[Bytes0, Address], + value: U256, + data: Bytes, + gas: Uint, + env: Environment, + code_address: Optional[Address] = None, + should_transfer_value: bool = True, +) -> Message: + """ + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.tangerine_whistle.vm.Message` + Items containing contract creation or message call specific data. + """ + if isinstance(target, Bytes0): + current_target = compute_contract_address( + caller, + get_account(env.state, caller).nonce - U256(1), + ) + msg_data = Bytes(b"") + code = data + elif isinstance(target, Address): + current_target = target + msg_data = data + code = get_account(env.state, target).code + if code_address is None: + code_address = target + else: + raise AssertionError("Target must be address or empty bytes") + + return Message( + caller=caller, + target=target, + gas=gas, + value=value, + data=msg_data, + code=code, + depth=Uint(0), + current_target=current_target, + code_address=code_address, + should_transfer_value=should_transfer_value, + parent_evm=None, + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/__init__.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/__init__.md new file mode 100644 index 00000000..81695232 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/__init__.md @@ -0,0 +1,121 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/__init__.py) + +```python +""" +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`. +""" + +from dataclasses import dataclass +from typing import List, Optional, Set, Tuple, Union + +from ethereum.base_types import U256, Bytes, Bytes0, Uint +from ethereum.crypto.hash import Hash32 + +from ..blocks import Log +from ..fork_types import Address +from ..state import State + +__all__ = ("Environment", "Evm", "Message") + + +@dataclass +class Environment: + """ + Items external to the virtual machine itself, provided by the environment. + """ + + caller: Address + block_hashes: List[Hash32] + origin: Address + coinbase: Address + number: Uint + gas_limit: Uint + gas_price: Uint + time: U256 + difficulty: Uint + state: State + traces: List[dict] + + +@dataclass +class Message: + """ + Items that are used by contract creation or message call. + """ + + caller: Address + target: Union[Bytes0, Address] + current_target: Address + gas: Uint + value: U256 + data: Bytes + code_address: Optional[Address] + code: Bytes + depth: Uint + should_transfer_value: bool + parent_evm: Optional["Evm"] + + +@dataclass +class Evm: + """The internal state of the virtual machine.""" + + pc: Uint + stack: List[U256] + memory: bytearray + code: Bytes + gas_left: Uint + env: Environment + valid_jump_destinations: Set[Uint] + logs: Tuple[Log, ...] + refund_counter: U256 + running: bool + message: Message + output: Bytes + accounts_to_delete: Set[Address] + error: Optional[Exception] + + +def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left + evm.logs += child_evm.logs + evm.refund_counter += child_evm.refund_counter + evm.accounts_to_delete.update(child_evm.accounts_to_delete) + + +def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None: + """ + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + """ + evm.gas_left += child_evm.gas_left +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/exceptions.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/exceptions.md new file mode 100644 index 00000000..29c8332f --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/exceptions.md @@ -0,0 +1,93 @@ +# ๐Ÿ exceptions.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/exceptions.py) + +```python +""" +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +""" + +from ethereum.exceptions import EthereumException + + +class ExceptionalHalt(EthereumException): + """ + Indicates that the EVM has experienced an exceptional halt. This causes + execution to immediately end with all gas being consumed. + """ + + +class StackUnderflowError(ExceptionalHalt): + """ + Occurs when a pop is executed on an empty stack. + """ + + pass + + +class StackOverflowError(ExceptionalHalt): + """ + Occurs when a push is executed on a stack at max capacity. + """ + + pass + + +class OutOfGasError(ExceptionalHalt): + """ + Occurs when an operation costs more than the amount of gas left in the + frame. + """ + + pass + + +class InvalidOpcode(ExceptionalHalt): + """ + Raised when an invalid opcode is encountered. + """ + + code: int + + def __init__(self, code: int) -> None: + super().__init__(code) + self.code = code + + +class InvalidJumpDestError(ExceptionalHalt): + """ + Occurs when the destination of a jump operation doesn't meet any of the + following criteria: + + * 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. + """ + + +class StackDepthLimitError(ExceptionalHalt): + """ + Raised when the message depth is greater than `1024` + """ + + pass + + +class AddressCollision(ExceptionalHalt): + """ + Raised when the new contract address has a collision. + """ + + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/gas.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/gas.md new file mode 100644 index 00000000..71445ea7 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/gas.md @@ -0,0 +1,244 @@ +# ๐Ÿ gas.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/gas.py) + +```python +""" +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +""" +from dataclasses import dataclass +from typing import List, Tuple + +from ethereum.base_types import U256, Uint +from ethereum.trace import GasAndRefund, evm_trace +from ethereum.utils.numeric import ceil32 + +from . import Evm +from .exceptions import OutOfGasError + +GAS_JUMPDEST = Uint(1) +GAS_BASE = Uint(2) +GAS_VERY_LOW = Uint(3) +GAS_SLOAD = Uint(200) +GAS_STORAGE_SET = Uint(20000) +GAS_STORAGE_UPDATE = Uint(5000) +GAS_STORAGE_CLEAR_REFUND = Uint(15000) +GAS_LOW = Uint(5) +GAS_MID = Uint(8) +GAS_HIGH = Uint(10) +GAS_EXPONENTIATION = Uint(10) +GAS_EXPONENTIATION_PER_BYTE = Uint(10) +GAS_MEMORY = Uint(3) +GAS_KECCAK256 = Uint(30) +GAS_KECCAK256_WORD = Uint(6) +GAS_COPY = Uint(3) +GAS_BLOCK_HASH = Uint(20) +GAS_EXTERNAL = Uint(700) +GAS_BALANCE = Uint(400) +GAS_LOG = Uint(375) +GAS_LOG_DATA = Uint(8) +GAS_LOG_TOPIC = Uint(375) +GAS_CREATE = Uint(32000) +GAS_CODE_DEPOSIT = Uint(200) +GAS_ZERO = Uint(0) +GAS_CALL = Uint(700) +GAS_NEW_ACCOUNT = Uint(25000) +GAS_CALL_VALUE = Uint(9000) +GAS_CALL_STIPEND = Uint(2300) +GAS_SELF_DESTRUCT = Uint(5000) +GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) +REFUND_SELF_DESTRUCT = Uint(24000) +GAS_ECRECOVER = Uint(3000) +GAS_SHA256 = Uint(60) +GAS_SHA256_WORD = Uint(12) +GAS_RIPEMD160 = Uint(600) +GAS_RIPEMD160_WORD = Uint(120) +GAS_IDENTITY = Uint(15) +GAS_IDENTITY_WORD = Uint(3) + + +@dataclass +class ExtendMemory: + """ + Define the parameters for memory extension in opcodes + + `cost`: `ethereum.base_types.Uint` + The gas required to perform the extension + `expand_by`: `ethereum.base_types.Uint` + The size by which the memory will be extended + """ + + cost: Uint + expand_by: Uint + + +@dataclass +class MessageCallGas: + """ + Define the gas cost and stipend for executing the call opcodes. + + `cost`: `ethereum.base_types.Uint` + The non-refundable portion of gas reserved for executing the + call opcode. + `stipend`: `ethereum.base_types.Uint` + The portion of gas available to sub-calls that is refundable + if not consumed + """ + + cost: Uint + stipend: Uint + + +def charge_gas(evm: Evm, amount: Uint) -> None: + """ + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + """ + evm_trace(evm, GasAndRefund(amount)) + + if evm.gas_left < amount: + raise OutOfGasError + else: + evm.gas_left -= U256(amount) + + +def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: + """ + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + """ + size_in_words = ceil32(size_in_bytes) // 32 + linear_cost = size_in_words * GAS_MEMORY + quadratic_cost = size_in_words**2 // 512 + total_gas_cost = linear_cost + quadratic_cost + try: + return total_gas_cost + except ValueError: + raise OutOfGasError + + +def calculate_gas_extend_memory( + memory: bytearray, extensions: List[Tuple[U256, U256]] +) -> ExtendMemory: + """ + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + """ + size_to_extend = Uint(0) + to_be_paid = Uint(0) + current_size = Uint(len(memory)) + for start_position, size in extensions: + if size == 0: + continue + before_size = ceil32(current_size) + after_size = ceil32(Uint(start_position) + Uint(size)) + if after_size <= before_size: + continue + + size_to_extend += after_size - before_size + already_paid = calculate_memory_gas_cost(before_size) + total_cost = calculate_memory_gas_cost(after_size) + to_be_paid += total_cost - already_paid + + current_size = after_size + + return ExtendMemory(to_be_paid, size_to_extend) + + +def calculate_message_call_gas( + value: U256, + gas: Uint, + gas_left: Uint, + memory_cost: Uint, + extra_gas: Uint, + call_stipend: Uint = GAS_CALL_STIPEND, +) -> MessageCallGas: + """ + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + """ + call_stipend = Uint(0) if value == 0 else call_stipend + if gas_left < extra_gas + memory_cost: + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + + return MessageCallGas(gas + extra_gas, gas + call_stipend) + + +def max_message_call_gas(gas: Uint) -> Uint: + """ + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + """ + return gas - (gas // 64) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/__init__.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/__init__.md new file mode 100644 index 00000000..92305b8a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/__init__.md @@ -0,0 +1,336 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/__init__.py) + +```python +""" +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +""" + +import enum +from typing import Callable, Dict + +from . import arithmetic as arithmetic_instructions +from . import bitwise as bitwise_instructions +from . import block as block_instructions +from . import comparison as comparison_instructions +from . import control_flow as control_flow_instructions +from . import environment as environment_instructions +from . import keccak as keccak_instructions +from . import log as log_instructions +from . import memory as memory_instructions +from . import stack as stack_instructions +from . import storage as storage_instructions +from . import system as system_instructions + + +class Ops(enum.Enum): + """ + Enum for EVM Opcodes + """ + + # Arithmetic Ops + ADD = 0x01 + MUL = 0x02 + SUB = 0x03 + DIV = 0x04 + SDIV = 0x05 + MOD = 0x06 + SMOD = 0x07 + ADDMOD = 0x08 + MULMOD = 0x09 + EXP = 0x0A + SIGNEXTEND = 0x0B + + # Comparison Ops + LT = 0x10 + GT = 0x11 + SLT = 0x12 + SGT = 0x13 + EQ = 0x14 + ISZERO = 0x15 + + # Bitwise Ops + AND = 0x16 + OR = 0x17 + XOR = 0x18 + NOT = 0x19 + BYTE = 0x1A + + # Keccak Op + KECCAK = 0x20 + + # Environmental Ops + ADDRESS = 0x30 + BALANCE = 0x31 + ORIGIN = 0x32 + CALLER = 0x33 + CALLVALUE = 0x34 + CALLDATALOAD = 0x35 + CALLDATASIZE = 0x36 + CALLDATACOPY = 0x37 + CODESIZE = 0x38 + CODECOPY = 0x39 + GASPRICE = 0x3A + EXTCODESIZE = 0x3B + EXTCODECOPY = 0x3C + + # Block Ops + BLOCKHASH = 0x40 + COINBASE = 0x41 + TIMESTAMP = 0x42 + NUMBER = 0x43 + DIFFICULTY = 0x44 + GASLIMIT = 0x45 + + # Control Flow Ops + STOP = 0x00 + JUMP = 0x56 + JUMPI = 0x57 + PC = 0x58 + GAS = 0x5A + JUMPDEST = 0x5B + + # Storage Ops + SLOAD = 0x54 + SSTORE = 0x55 + + # Pop Operation + POP = 0x50 + + # Push Operations + PUSH1 = 0x60 + PUSH2 = 0x61 + PUSH3 = 0x62 + PUSH4 = 0x63 + PUSH5 = 0x64 + PUSH6 = 0x65 + PUSH7 = 0x66 + PUSH8 = 0x67 + PUSH9 = 0x68 + PUSH10 = 0x69 + PUSH11 = 0x6A + PUSH12 = 0x6B + PUSH13 = 0x6C + PUSH14 = 0x6D + PUSH15 = 0x6E + PUSH16 = 0x6F + PUSH17 = 0x70 + PUSH18 = 0x71 + PUSH19 = 0x72 + PUSH20 = 0x73 + PUSH21 = 0x74 + PUSH22 = 0x75 + PUSH23 = 0x76 + PUSH24 = 0x77 + PUSH25 = 0x78 + PUSH26 = 0x79 + PUSH27 = 0x7A + PUSH28 = 0x7B + PUSH29 = 0x7C + PUSH30 = 0x7D + PUSH31 = 0x7E + PUSH32 = 0x7F + + # Dup operations + DUP1 = 0x80 + DUP2 = 0x81 + DUP3 = 0x82 + DUP4 = 0x83 + DUP5 = 0x84 + DUP6 = 0x85 + DUP7 = 0x86 + DUP8 = 0x87 + DUP9 = 0x88 + DUP10 = 0x89 + DUP11 = 0x8A + DUP12 = 0x8B + DUP13 = 0x8C + DUP14 = 0x8D + DUP15 = 0x8E + DUP16 = 0x8F + + # Swap operations + SWAP1 = 0x90 + SWAP2 = 0x91 + SWAP3 = 0x92 + SWAP4 = 0x93 + SWAP5 = 0x94 + SWAP6 = 0x95 + SWAP7 = 0x96 + SWAP8 = 0x97 + SWAP9 = 0x98 + SWAP10 = 0x99 + SWAP11 = 0x9A + SWAP12 = 0x9B + SWAP13 = 0x9C + SWAP14 = 0x9D + SWAP15 = 0x9E + SWAP16 = 0x9F + + # Memory Operations + MLOAD = 0x51 + MSTORE = 0x52 + MSTORE8 = 0x53 + MSIZE = 0x59 + + # Log Operations + LOG0 = 0xA0 + LOG1 = 0xA1 + LOG2 = 0xA2 + LOG3 = 0xA3 + LOG4 = 0xA4 + + # System Operations + CREATE = 0xF0 + RETURN = 0xF3 + CALL = 0xF1 + CALLCODE = 0xF2 + DELEGATECALL = 0xF4 + SELFDESTRUCT = 0xFF + + +op_implementation: Dict[Ops, Callable] = { + Ops.STOP: control_flow_instructions.stop, + Ops.ADD: arithmetic_instructions.add, + Ops.MUL: arithmetic_instructions.mul, + Ops.SUB: arithmetic_instructions.sub, + Ops.DIV: arithmetic_instructions.div, + Ops.SDIV: arithmetic_instructions.sdiv, + Ops.MOD: arithmetic_instructions.mod, + Ops.SMOD: arithmetic_instructions.smod, + Ops.ADDMOD: arithmetic_instructions.addmod, + Ops.MULMOD: arithmetic_instructions.mulmod, + Ops.EXP: arithmetic_instructions.exp, + Ops.SIGNEXTEND: arithmetic_instructions.signextend, + Ops.LT: comparison_instructions.less_than, + Ops.GT: comparison_instructions.greater_than, + Ops.SLT: comparison_instructions.signed_less_than, + Ops.SGT: comparison_instructions.signed_greater_than, + Ops.EQ: comparison_instructions.equal, + Ops.ISZERO: comparison_instructions.is_zero, + Ops.AND: bitwise_instructions.bitwise_and, + Ops.OR: bitwise_instructions.bitwise_or, + Ops.XOR: bitwise_instructions.bitwise_xor, + Ops.NOT: bitwise_instructions.bitwise_not, + Ops.BYTE: bitwise_instructions.get_byte, + Ops.KECCAK: keccak_instructions.keccak, + Ops.SLOAD: storage_instructions.sload, + Ops.BLOCKHASH: block_instructions.block_hash, + Ops.COINBASE: block_instructions.coinbase, + Ops.TIMESTAMP: block_instructions.timestamp, + Ops.NUMBER: block_instructions.number, + Ops.DIFFICULTY: block_instructions.difficulty, + Ops.GASLIMIT: block_instructions.gas_limit, + Ops.MLOAD: memory_instructions.mload, + Ops.MSTORE: memory_instructions.mstore, + Ops.MSTORE8: memory_instructions.mstore8, + Ops.MSIZE: memory_instructions.msize, + Ops.ADDRESS: environment_instructions.address, + Ops.BALANCE: environment_instructions.balance, + Ops.ORIGIN: environment_instructions.origin, + Ops.CALLER: environment_instructions.caller, + Ops.CALLVALUE: environment_instructions.callvalue, + Ops.CALLDATALOAD: environment_instructions.calldataload, + Ops.CALLDATASIZE: environment_instructions.calldatasize, + Ops.CALLDATACOPY: environment_instructions.calldatacopy, + Ops.CODESIZE: environment_instructions.codesize, + Ops.CODECOPY: environment_instructions.codecopy, + Ops.GASPRICE: environment_instructions.gasprice, + Ops.EXTCODESIZE: environment_instructions.extcodesize, + Ops.EXTCODECOPY: environment_instructions.extcodecopy, + Ops.SSTORE: storage_instructions.sstore, + Ops.JUMP: control_flow_instructions.jump, + Ops.JUMPI: control_flow_instructions.jumpi, + Ops.PC: control_flow_instructions.pc, + Ops.GAS: control_flow_instructions.gas_left, + Ops.JUMPDEST: control_flow_instructions.jumpdest, + Ops.POP: stack_instructions.pop, + Ops.PUSH1: stack_instructions.push1, + Ops.PUSH2: stack_instructions.push2, + Ops.PUSH3: stack_instructions.push3, + Ops.PUSH4: stack_instructions.push4, + Ops.PUSH5: stack_instructions.push5, + Ops.PUSH6: stack_instructions.push6, + Ops.PUSH7: stack_instructions.push7, + Ops.PUSH8: stack_instructions.push8, + Ops.PUSH9: stack_instructions.push9, + Ops.PUSH10: stack_instructions.push10, + Ops.PUSH11: stack_instructions.push11, + Ops.PUSH12: stack_instructions.push12, + Ops.PUSH13: stack_instructions.push13, + Ops.PUSH14: stack_instructions.push14, + Ops.PUSH15: stack_instructions.push15, + Ops.PUSH16: stack_instructions.push16, + Ops.PUSH17: stack_instructions.push17, + Ops.PUSH18: stack_instructions.push18, + Ops.PUSH19: stack_instructions.push19, + Ops.PUSH20: stack_instructions.push20, + Ops.PUSH21: stack_instructions.push21, + Ops.PUSH22: stack_instructions.push22, + Ops.PUSH23: stack_instructions.push23, + Ops.PUSH24: stack_instructions.push24, + Ops.PUSH25: stack_instructions.push25, + Ops.PUSH26: stack_instructions.push26, + Ops.PUSH27: stack_instructions.push27, + Ops.PUSH28: stack_instructions.push28, + Ops.PUSH29: stack_instructions.push29, + Ops.PUSH30: stack_instructions.push30, + Ops.PUSH31: stack_instructions.push31, + Ops.PUSH32: stack_instructions.push32, + Ops.DUP1: stack_instructions.dup1, + Ops.DUP2: stack_instructions.dup2, + Ops.DUP3: stack_instructions.dup3, + Ops.DUP4: stack_instructions.dup4, + Ops.DUP5: stack_instructions.dup5, + Ops.DUP6: stack_instructions.dup6, + Ops.DUP7: stack_instructions.dup7, + Ops.DUP8: stack_instructions.dup8, + Ops.DUP9: stack_instructions.dup9, + Ops.DUP10: stack_instructions.dup10, + Ops.DUP11: stack_instructions.dup11, + Ops.DUP12: stack_instructions.dup12, + Ops.DUP13: stack_instructions.dup13, + Ops.DUP14: stack_instructions.dup14, + Ops.DUP15: stack_instructions.dup15, + Ops.DUP16: stack_instructions.dup16, + Ops.SWAP1: stack_instructions.swap1, + Ops.SWAP2: stack_instructions.swap2, + Ops.SWAP3: stack_instructions.swap3, + Ops.SWAP4: stack_instructions.swap4, + Ops.SWAP5: stack_instructions.swap5, + Ops.SWAP6: stack_instructions.swap6, + Ops.SWAP7: stack_instructions.swap7, + Ops.SWAP8: stack_instructions.swap8, + Ops.SWAP9: stack_instructions.swap9, + Ops.SWAP10: stack_instructions.swap10, + Ops.SWAP11: stack_instructions.swap11, + Ops.SWAP12: stack_instructions.swap12, + Ops.SWAP13: stack_instructions.swap13, + Ops.SWAP14: stack_instructions.swap14, + Ops.SWAP15: stack_instructions.swap15, + Ops.SWAP16: stack_instructions.swap16, + Ops.LOG0: log_instructions.log0, + Ops.LOG1: log_instructions.log1, + Ops.LOG2: log_instructions.log2, + Ops.LOG3: log_instructions.log3, + Ops.LOG4: log_instructions.log4, + Ops.CREATE: system_instructions.create, + Ops.RETURN: system_instructions.return_, + Ops.CALL: system_instructions.call, + Ops.CALLCODE: system_instructions.callcode, + Ops.DELEGATECALL: system_instructions.delegatecall, + Ops.SELFDESTRUCT: system_instructions.selfdestruct, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/arithmetic.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/arithmetic.md new file mode 100644 index 00000000..228df5b4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/arithmetic.md @@ -0,0 +1,375 @@ +# ๐Ÿ arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/arithmetic.py) + +```python +""" +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +""" + +from ethereum.base_types import U255_CEIL_VALUE, U256, U256_CEIL_VALUE, Uint +from ethereum.utils.numeric import get_sign + +from .. import Evm +from ..gas import ( + GAS_EXPONENTIATION, + GAS_EXPONENTIATION_PER_BYTE, + GAS_LOW, + GAS_MID, + GAS_VERY_LOW, + charge_gas, +) +from ..stack import pop, push + + +def add(evm: Evm) -> None: + """ + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_add(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sub(evm: Evm) -> None: + """ + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = x.wrapping_sub(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mul(evm: Evm) -> None: + """ + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + result = x.wrapping_mul(y) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def div(evm: Evm) -> None: + """ + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack) + divisor = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = U256(0) + else: + quotient = dividend // divisor + + push(evm.stack, quotient) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sdiv(evm: Evm) -> None: + """ + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + dividend = pop(evm.stack).to_signed() + divisor = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if divisor == 0: + quotient = 0 + elif dividend == -U255_CEIL_VALUE and divisor == -1: + quotient = -U255_CEIL_VALUE + else: + sign = get_sign(dividend * divisor) + quotient = sign * (abs(dividend) // abs(divisor)) + + push(evm.stack, U256.from_signed(quotient)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mod(evm: Evm) -> None: + """ + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = U256(0) + else: + remainder = x % y + + push(evm.stack, remainder) + + # PROGRAM COUNTER + evm.pc += 1 + + +def smod(evm: Evm) -> None: + """ + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack).to_signed() + y = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if y == 0: + remainder = 0 + else: + remainder = get_sign(x) * (abs(x) % abs(y)) + + push(evm.stack, U256.from_signed(remainder)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def addmod(evm: Evm) -> None: + """ + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x + y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mulmod(evm: Evm) -> None: + """ + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = Uint(pop(evm.stack)) + y = Uint(pop(evm.stack)) + z = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if z == 0: + result = U256(0) + else: + result = U256((x * y) % z) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def exp(evm: Evm) -> None: + """ + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + base = Uint(pop(evm.stack)) + exponent = Uint(pop(evm.stack)) + + # GAS + # This is equivalent to 1 + floor(log(y, 256)). But in python the log + # function is inaccurate leading to wrong results. + exponent_bits = exponent.bit_length() + exponent_bytes = (exponent_bits + 7) // 8 + charge_gas( + evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + ) + + # OPERATION + result = U256(pow(base, exponent, U256_CEIL_VALUE)) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signextend(evm: Evm) -> None: + """ + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + byte_num = pop(evm.stack) + value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_LOW) + + # OPERATION + if byte_num > 31: + # Can't extend any further + result = value + else: + # U256(0).to_be_bytes() gives b'' instead b'\x00'. + value_bytes = bytes(value.to_be_bytes32()) + # Now among the obtained value bytes, consider only + # N `least significant bytes`, where N is `byte_num + 1`. + value_bytes = value_bytes[31 - int(byte_num) :] + sign_bit = value_bytes[0] >> 7 + if sign_bit == 0: + result = U256.from_be_bytes(value_bytes) + else: + num_bytes_prepend = 32 - (byte_num + 1) + result = U256.from_be_bytes( + bytearray([0xFF] * num_bytes_prepend) + value_bytes + ) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/bitwise.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/bitwise.md new file mode 100644 index 00000000..b0803624 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/bitwise.md @@ -0,0 +1,160 @@ +# ๐Ÿ bitwise.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/bitwise.py) + +```python +""" +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def bitwise_and(evm: Evm) -> None: + """ + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x & y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_or(evm: Evm) -> None: + """ + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x | y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_xor(evm: Evm) -> None: + """ + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + y = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, x ^ y) + + # PROGRAM COUNTER + evm.pc += 1 + + +def bitwise_not(evm: Evm) -> None: + """ + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + push(evm.stack, ~x) + + # PROGRAM COUNTER + evm.pc += 1 + + +def get_byte(evm: Evm) -> None: + """ + 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. + + """ + # STACK + byte_index = pop(evm.stack) + word = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + if byte_index >= 32: + result = U256(0) + else: + extra_bytes_to_right = 31 - byte_index + # Remove the extra bytes in the right + word = word >> (extra_bytes_to_right * 8) + # Remove the extra bytes in the left + word = word & 0xFF + result = U256(word) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/block.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/block.md new file mode 100644 index 00000000..2a67b348 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/block.md @@ -0,0 +1,189 @@ +# ๐Ÿ block.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/block.py) + +```python +""" +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..stack import pop, push + + +def block_hash(evm: Evm) -> None: + """ + 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. + + """ + # STACK + block_number = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BLOCK_HASH) + + # OPERATION + if evm.env.number <= block_number or evm.env.number > block_number + 256: + # Default hash to 0, if the block of interest is not yet on the chain + # (including the block which has the current executing transaction), + # or if the block's age is more than 256. + hash = b"\x00" + else: + hash = evm.env.block_hashes[-(evm.env.number - block_number)] + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def coinbase(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.coinbase)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def timestamp(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.env.time) + + # PROGRAM COUNTER + evm.pc += 1 + + +def number(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.number)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def difficulty(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.difficulty)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_limit(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_limit)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/comparison.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/comparison.md new file mode 100644 index 00000000..a0fdf4d5 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/comparison.md @@ -0,0 +1,184 @@ +# ๐Ÿ comparison.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/comparison.py) + +```python +""" +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +""" + +from ethereum.base_types import U256 + +from .. import Evm +from ..gas import GAS_VERY_LOW, charge_gas +from ..stack import pop, push + + +def less_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_less_than(evm: Evm) -> None: + """ + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left < right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def greater_than(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def signed_greater_than(evm: Evm) -> None: + """ + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + left = pop(evm.stack).to_signed() + right = pop(evm.stack).to_signed() + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left > right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def equal(evm: Evm) -> None: + """ + 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. + + """ + # STACK + left = pop(evm.stack) + right = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(left == right) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 + + +def is_zero(evm: Evm) -> None: + """ + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + x = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + result = U256(x == 0) + + push(evm.stack, result) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/control_flow.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/control_flow.md new file mode 100644 index 00000000..58b750ab --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/control_flow.md @@ -0,0 +1,177 @@ +# ๐Ÿ control_flow.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/control_flow.py) + +```python +""" +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +""" + +from ethereum.base_types import U256, Uint + +from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from .. import Evm +from ..exceptions import InvalidJumpDestError +from ..stack import pop, push + + +def stop(evm: Evm) -> None: + """ + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + pass + + # GAS + pass + + # OPERATION + evm.running = False + + # PROGRAM COUNTER + evm.pc += 1 + + +def jump(evm: Evm) -> None: + """ + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_MID) + + # OPERATION + if jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + + # PROGRAM COUNTER + evm.pc = Uint(jump_dest) + + +def jumpi(evm: Evm) -> None: + """ + 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. + + """ + # STACK + jump_dest = Uint(pop(evm.stack)) + conditional_value = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_HIGH) + + # OPERATION + if conditional_value == 0: + destination = evm.pc + 1 + elif jump_dest not in evm.valid_jump_destinations: + raise InvalidJumpDestError + else: + destination = jump_dest + + # PROGRAM COUNTER + evm.pc = Uint(destination) + + +def pc(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.pc)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gas_left(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.gas_left)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def jumpdest(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_JUMPDEST) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/environment.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/environment.md new file mode 100644 index 00000000..f0bb0a70 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/environment.md @@ -0,0 +1,381 @@ +# ๐Ÿ environment.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/environment.py) + +```python +""" +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.utils.numeric import ceil32 + +from ...state import get_account +from ...utils.address import to_address +from ...vm.memory import buffer_read, memory_write +from .. import Evm +from ..gas import ( + GAS_BALANCE, + GAS_BASE, + GAS_COPY, + GAS_EXTERNAL, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..stack import pop, push + + +def address(evm: Evm) -> None: + """ + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.current_target)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def balance(evm: Evm) -> None: + """ + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_BALANCE) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. + balance = get_account(evm.env.state, address).balance + + push(evm.stack, balance) + + # PROGRAM COUNTER + evm.pc += 1 + + +def origin(evm: Evm) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.env.origin)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def caller(evm: Evm) -> None: + """ + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256.from_be_bytes(evm.message.caller)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callvalue(evm: Evm) -> None: + """ + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, evm.message.value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldataload(evm: Evm) -> None: + """ + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_index = pop(evm.stack) + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + value = buffer_read(evm.message.data, start_index, U256(32)) + + push(evm.stack, U256.from_be_bytes(value)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatasize(evm: Evm) -> None: + """ + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.message.data))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def calldatacopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + data_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.message.data, data_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codesize(evm: Evm) -> None: + """ + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.code))) + + # PROGRAM COUNTER + evm.pc += 1 + + +def codecopy(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = buffer_read(evm.code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def gasprice(evm: Evm) -> None: + """ + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(evm.env.gas_price)) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodesize(evm: Evm) -> None: + """ + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + + # GAS + charge_gas(evm, GAS_EXTERNAL) + + # OPERATION + # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. + codesize = U256(len(get_account(evm.env.state, address).code)) + + push(evm.stack, codesize) + + # PROGRAM COUNTER + evm.pc += 1 + + +def extcodecopy(evm: Evm) -> None: + """ + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + address = to_address(pop(evm.stack)) + memory_start_index = pop(evm.stack) + code_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + copy_gas_cost = GAS_COPY * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + code = get_account(evm.env.state, address).code + value = buffer_read(code, code_start_index, size) + memory_write(evm.memory, memory_start_index, value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/keccak.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/keccak.md new file mode 100644 index 00000000..f5808528 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/keccak.md @@ -0,0 +1,69 @@ +# ๐Ÿ keccak.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/keccak.py) + +```python +""" +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +""" + +from ethereum.base_types import U256, Uint +from ethereum.crypto.hash import keccak256 +from ethereum.utils.numeric import ceil32 + +from .. import Evm +from ..gas import ( + GAS_KECCAK256, + GAS_KECCAK256_WORD, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop, push + + +def keccak(evm: Evm) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + # GAS + words = ceil32(Uint(size)) // 32 + word_gas_cost = GAS_KECCAK256_WORD * words + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + data = memory_read_bytes(evm.memory, memory_start_index, size) + hash = keccak256(data) + + push(evm.stack, U256.from_be_bytes(hash)) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/log.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/log.md new file mode 100644 index 00000000..9971accd --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/log.md @@ -0,0 +1,91 @@ +# ๐Ÿ log.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/log.py) + +```python +""" +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +""" +from functools import partial + +from ethereum.base_types import U256 + +from ...blocks import Log +from .. import Evm +from ..gas import ( + GAS_LOG, + GAS_LOG_DATA, + GAS_LOG_TOPIC, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes +from ..stack import pop + + +def log_n(evm: Evm, num_topics: U256) -> None: + """ + 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. + + """ + # STACK + memory_start_index = pop(evm.stack) + size = pop(evm.stack) + + topics = [] + for _ in range(num_topics): + topic = pop(evm.stack).to_be_bytes32() + topics.append(topic) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_index, size)] + ) + charge_gas( + evm, + GAS_LOG + + GAS_LOG_DATA * size + + GAS_LOG_TOPIC * num_topics + + extend_memory.cost, + ) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + log_entry = Log( + address=evm.message.current_target, + topics=tuple(topics), + data=memory_read_bytes(evm.memory, memory_start_index, size), + ) + + evm.logs = evm.logs + (log_entry,) + + # PROGRAM COUNTER + evm.pc += 1 + + +log0 = partial(log_n, num_topics=0) +log1 = partial(log_n, num_topics=1) +log2 = partial(log_n, num_topics=2) +log3 = partial(log_n, num_topics=3) +log4 = partial(log_n, num_topics=4) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/memory.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/memory.md new file mode 100644 index 00000000..1165ceee --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/memory.md @@ -0,0 +1,146 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +""" +from ethereum.base_types import U256, Bytes + +from .. import Evm +from ..gas import ( + GAS_BASE, + GAS_VERY_LOW, + calculate_gas_extend_memory, + charge_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def mstore(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack).to_be_bytes32() + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(len(value)))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + memory_write(evm.memory, start_position, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mstore8(evm: Evm) -> None: + """ + 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. + + """ + # STACK + start_position = pop(evm.stack) + value = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(1))] + ) + + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + normalized_bytes_value = Bytes([value & 0xFF]) + memory_write(evm.memory, start_position, normalized_bytes_value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def mload(evm: Evm) -> None: + """ + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + start_position = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(start_position, U256(32))] + ) + charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + value = U256.from_be_bytes( + memory_read_bytes(evm.memory, start_position, U256(32)) + ) + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def msize(evm: Evm) -> None: + """ + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + push(evm.stack, U256(len(evm.memory))) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/stack.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/stack.md new file mode 100644 index 00000000..8657fed2 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/stack.md @@ -0,0 +1,214 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +""" + +from functools import partial + +from ethereum.base_types import U256 +from ethereum.utils.ensure import ensure + +from .. import Evm, stack +from ..exceptions import StackUnderflowError +from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..memory import buffer_read + + +def pop(evm: Evm) -> None: + """ + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + stack.pop(evm.stack) + + # GAS + charge_gas(evm, GAS_BASE) + + # OPERATION + pass + + # PROGRAM COUNTER + evm.pc += 1 + + +def push_n(evm: Evm, num_bytes: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + data_to_push = U256.from_be_bytes( + buffer_read(evm.code, U256(evm.pc + 1), U256(num_bytes)) + ) + stack.push(evm.stack, data_to_push) + + # PROGRAM COUNTER + evm.pc += 1 + num_bytes + + +def dup_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] + stack.push(evm.stack, data_to_duplicate) + + # PROGRAM COUNTER + evm.pc += 1 + + +def swap_n(evm: Evm, item_number: int) -> None: + """ + 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. + + """ + # STACK + pass + + # GAS + charge_gas(evm, GAS_VERY_LOW) + + # OPERATION + ensure(item_number < len(evm.stack), StackUnderflowError) + evm.stack[-1], evm.stack[-1 - item_number] = ( + evm.stack[-1 - item_number], + evm.stack[-1], + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +push1 = partial(push_n, num_bytes=1) +push2 = partial(push_n, num_bytes=2) +push3 = partial(push_n, num_bytes=3) +push4 = partial(push_n, num_bytes=4) +push5 = partial(push_n, num_bytes=5) +push6 = partial(push_n, num_bytes=6) +push7 = partial(push_n, num_bytes=7) +push8 = partial(push_n, num_bytes=8) +push9 = partial(push_n, num_bytes=9) +push10 = partial(push_n, num_bytes=10) +push11 = partial(push_n, num_bytes=11) +push12 = partial(push_n, num_bytes=12) +push13 = partial(push_n, num_bytes=13) +push14 = partial(push_n, num_bytes=14) +push15 = partial(push_n, num_bytes=15) +push16 = partial(push_n, num_bytes=16) +push17 = partial(push_n, num_bytes=17) +push18 = partial(push_n, num_bytes=18) +push19 = partial(push_n, num_bytes=19) +push20 = partial(push_n, num_bytes=20) +push21 = partial(push_n, num_bytes=21) +push22 = partial(push_n, num_bytes=22) +push23 = partial(push_n, num_bytes=23) +push24 = partial(push_n, num_bytes=24) +push25 = partial(push_n, num_bytes=25) +push26 = partial(push_n, num_bytes=26) +push27 = partial(push_n, num_bytes=27) +push28 = partial(push_n, num_bytes=28) +push29 = partial(push_n, num_bytes=29) +push30 = partial(push_n, num_bytes=30) +push31 = partial(push_n, num_bytes=31) +push32 = partial(push_n, num_bytes=32) + +dup1 = partial(dup_n, item_number=0) +dup2 = partial(dup_n, item_number=1) +dup3 = partial(dup_n, item_number=2) +dup4 = partial(dup_n, item_number=3) +dup5 = partial(dup_n, item_number=4) +dup6 = partial(dup_n, item_number=5) +dup7 = partial(dup_n, item_number=6) +dup8 = partial(dup_n, item_number=7) +dup9 = partial(dup_n, item_number=8) +dup10 = partial(dup_n, item_number=9) +dup11 = partial(dup_n, item_number=10) +dup12 = partial(dup_n, item_number=11) +dup13 = partial(dup_n, item_number=12) +dup14 = partial(dup_n, item_number=13) +dup15 = partial(dup_n, item_number=14) +dup16 = partial(dup_n, item_number=15) + +swap1 = partial(swap_n, item_number=1) +swap2 = partial(swap_n, item_number=2) +swap3 = partial(swap_n, item_number=3) +swap4 = partial(swap_n, item_number=4) +swap5 = partial(swap_n, item_number=5) +swap6 = partial(swap_n, item_number=6) +swap7 = partial(swap_n, item_number=7) +swap8 = partial(swap_n, item_number=8) +swap9 = partial(swap_n, item_number=9) +swap10 = partial(swap_n, item_number=10) +swap11 = partial(swap_n, item_number=11) +swap12 = partial(swap_n, item_number=12) +swap13 = partial(swap_n, item_number=13) +swap14 = partial(swap_n, item_number=14) +swap15 = partial(swap_n, item_number=15) +swap16 = partial(swap_n, item_number=16) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/storage.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/storage.md new file mode 100644 index 00000000..3c34495d --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/storage.md @@ -0,0 +1,89 @@ +# ๐Ÿ storage.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/storage.py) + +```python +""" +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +""" + +from ...state import get_storage, set_storage +from .. import Evm +from ..gas import ( + GAS_SLOAD, + GAS_STORAGE_CLEAR_REFUND, + GAS_STORAGE_SET, + GAS_STORAGE_UPDATE, + charge_gas, +) +from ..stack import pop, push + + +def sload(evm: Evm) -> None: + """ + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + + # GAS + charge_gas(evm, GAS_SLOAD) + + # OPERATION + value = get_storage(evm.env.state, evm.message.current_target, key) + + push(evm.stack, value) + + # PROGRAM COUNTER + evm.pc += 1 + + +def sstore(evm: Evm) -> None: + """ + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + """ + # STACK + key = pop(evm.stack).to_be_bytes32() + new_value = pop(evm.stack) + + # GAS + current_value = get_storage(evm.env.state, evm.message.current_target, key) + if new_value != 0 and current_value == 0: + gas_cost = GAS_STORAGE_SET + else: + gas_cost = GAS_STORAGE_UPDATE + + if new_value == 0 and current_value != 0: + evm.refund_counter += GAS_STORAGE_CLEAR_REFUND + + charge_gas(evm, gas_cost) + + # OPERATION + set_storage(evm.env.state, evm.message.current_target, key, new_value) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/system.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/system.md new file mode 100644 index 00000000..6df74ea4 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/instructions/system.md @@ -0,0 +1,457 @@ +# ๐Ÿ system.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/instructions/system.py) + +```python +""" +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +""" +from ethereum.base_types import U256, Bytes0, Uint + +from ...fork_types import Address +from ...state import ( + account_exists, + account_has_code_or_nonce, + get_account, + increment_nonce, + set_account_balance, +) +from ...utils.address import compute_contract_address, to_address +from .. import ( + Evm, + Message, + incorporate_child_on_error, + incorporate_child_on_success, +) +from ..gas import ( + GAS_CALL, + GAS_CALL_VALUE, + GAS_CREATE, + GAS_NEW_ACCOUNT, + GAS_SELF_DESTRUCT, + GAS_SELF_DESTRUCT_NEW_ACCOUNT, + GAS_ZERO, + REFUND_SELF_DESTRUCT, + calculate_gas_extend_memory, + calculate_message_call_gas, + charge_gas, + max_message_call_gas, +) +from ..memory import memory_read_bytes, memory_write +from ..stack import pop, push + + +def create(evm: Evm) -> None: + """ + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # This import causes a circular import error + # if it's not moved inside this method + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message + + # STACK + endowment = pop(evm.stack) + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_CREATE + extend_memory.cost) + + create_message_gas = max_message_call_gas(Uint(evm.gas_left)) + evm.gas_left -= create_message_gas + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_address = evm.message.current_target + sender = get_account(evm.env.state, sender_address) + + contract_address = compute_contract_address( + evm.message.current_target, + get_account(evm.env.state, evm.message.current_target).nonce, + ) + + if ( + sender.balance < endowment + or sender.nonce == Uint(2**64 - 1) + or evm.message.depth + 1 > STACK_DEPTH_LIMIT + ): + push(evm.stack, U256(0)) + evm.gas_left += create_message_gas + elif account_has_code_or_nonce(evm.env.state, contract_address): + increment_nonce(evm.env.state, evm.message.current_target) + push(evm.stack, U256(0)) + else: + call_data = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + increment_nonce(evm.env.state, evm.message.current_target) + + child_message = Message( + caller=evm.message.current_target, + target=Bytes0(), + gas=create_message_gas, + value=endowment, + data=b"", + code=call_data, + current_target=contract_address, + depth=evm.message.depth + 1, + code_address=None, + should_transfer_value=True, + parent_evm=evm, + ) + child_evm = process_create_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push( + evm.stack, U256.from_be_bytes(child_evm.message.current_target) + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def return_(evm: Evm) -> None: + """ + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + memory_start_position = pop(evm.stack) + memory_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, [(memory_start_position, memory_size)] + ) + + charge_gas(evm, GAS_ZERO + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + evm.output = memory_read_bytes( + evm.memory, memory_start_position, memory_size + ) + + evm.running = False + + # PROGRAM COUNTER + pass + + +def 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, +) -> None: + """ + Perform the core logic of the `CALL*` family of opcodes. + """ + from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message + + if evm.message.depth + 1 > STACK_DEPTH_LIMIT: + evm.gas_left += gas + push(evm.stack, U256(0)) + return + + call_data = memory_read_bytes( + evm.memory, memory_input_start_position, memory_input_size + ) + code = get_account(evm.env.state, code_address).code + child_message = Message( + caller=caller, + target=to, + gas=gas, + value=value, + data=call_data, + code=code, + current_target=to, + depth=evm.message.depth + 1, + code_address=code_address, + should_transfer_value=should_transfer_value, + parent_evm=evm, + ) + child_evm = process_message(child_message, evm.env) + + if child_evm.error: + incorporate_child_on_error(evm, child_evm) + push(evm.stack, U256(0)) + else: + incorporate_child_on_success(evm, child_evm) + push(evm.stack, U256(1)) + + actual_output_size = min(memory_output_size, U256(len(child_evm.output))) + memory_write( + evm.memory, + memory_output_start_position, + child_evm.output[:actual_output_size], + ) + + +def call(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + to = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + _account_exists = account_exists(evm.env.state, to) + create_gas_cost = Uint(0) if _account_exists else GAS_NEW_ACCOUNT + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + create_gas_cost + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + to, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def callcode(evm: Evm) -> None: + """ + Message-call into this account with alternative accountโ€™s code. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + value = pop(evm.stack) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + to = evm.message.current_target + + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + message_call_gas = calculate_message_call_gas( + value, + gas, + Uint(evm.gas_left), + extend_memory.cost, + GAS_CALL + transfer_gas_cost, + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + sender_balance = get_account( + evm.env.state, evm.message.current_target + ).balance + if sender_balance < value: + push(evm.stack, U256(0)) + evm.gas_left += message_call_gas.stipend + else: + generic_call( + evm, + message_call_gas.stipend, + value, + evm.message.current_target, + to, + code_address, + True, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 + + +def selfdestruct(evm: Evm) -> None: + """ + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + beneficiary = to_address(pop(evm.stack)) + + # GAS + gas_cost = GAS_SELF_DESTRUCT + if not account_exists(evm.env.state, beneficiary): + gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + + originator = evm.message.current_target + + refunded_accounts = evm.accounts_to_delete + parent_evm = evm.message.parent_evm + while parent_evm is not None: + refunded_accounts.update(parent_evm.accounts_to_delete) + parent_evm = parent_evm.message.parent_evm + + if originator not in refunded_accounts: + evm.refund_counter += REFUND_SELF_DESTRUCT + + charge_gas(evm, gas_cost) + + # OPERATION + beneficiary_balance = get_account(evm.env.state, beneficiary).balance + originator_balance = get_account(evm.env.state, originator).balance + + # First Transfer to beneficiary + set_account_balance( + evm.env.state, beneficiary, beneficiary_balance + originator_balance + ) + # Next, Zero the balance of the address being deleted (must come after + # sending to beneficiary in case the contract named itself as the + # beneficiary). + set_account_balance(evm.env.state, originator, U256(0)) + + # register account for deletion + evm.accounts_to_delete.add(originator) + + # HALT the execution + evm.running = False + + # PROGRAM COUNTER + pass + + +def delegatecall(evm: Evm) -> None: + """ + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + """ + # STACK + gas = Uint(pop(evm.stack)) + code_address = to_address(pop(evm.stack)) + memory_input_start_position = pop(evm.stack) + memory_input_size = pop(evm.stack) + memory_output_start_position = pop(evm.stack) + memory_output_size = pop(evm.stack) + + # GAS + extend_memory = calculate_gas_extend_memory( + evm.memory, + [ + (memory_input_start_position, memory_input_size), + (memory_output_start_position, memory_output_size), + ], + ) + message_call_gas = calculate_message_call_gas( + U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + ) + charge_gas(evm, message_call_gas.cost + extend_memory.cost) + + # OPERATION + evm.memory += b"\x00" * extend_memory.expand_by + generic_call( + evm, + message_call_gas.stipend, + evm.message.value, + evm.message.caller, + evm.message.current_target, + code_address, + False, + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size, + ) + + # PROGRAM COUNTER + evm.pc += 1 +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/interpreter.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/interpreter.md new file mode 100644 index 00000000..0fb0a4df --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/interpreter.md @@ -0,0 +1,279 @@ +# ๐Ÿ interpreter.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/interpreter.py) + +```python +""" +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +""" +from dataclasses import dataclass +from typing import Optional, Set, Tuple + +from ethereum.base_types import U256, Bytes0, Uint +from ethereum.trace import ( + EvmStop, + OpEnd, + OpException, + OpStart, + PrecompileEnd, + PrecompileStart, + TransactionEnd, + evm_trace, +) + +from ..blocks import Log +from ..fork_types import Address +from ..state import ( + account_has_code_or_nonce, + begin_transaction, + commit_transaction, + destroy_storage, + move_ether, + rollback_transaction, + set_code, + touch_account, +) +from ..vm import Message +from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas +from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS +from . import Environment, Evm +from .exceptions import ( + AddressCollision, + ExceptionalHalt, + InvalidOpcode, + StackDepthLimitError, +) +from .instructions import Ops, op_implementation +from .runtime import get_valid_jump_destinations + +STACK_DEPTH_LIMIT = U256(1024) + + +@dataclass +class MessageCallOutput: + """ + Output of a particular message call + + Contains the following: + + 1. `gas_left`: remaining gas after execution. + 2. `refund_counter`: gas to refund after execution. + 3. `logs`: list of `Log` generated during execution. + 4. `accounts_to_delete`: Contracts which have self-destructed. + 5. `error`: The error from the execution if any. + """ + + gas_left: Uint + refund_counter: U256 + logs: Tuple[Log, ...] + accounts_to_delete: Set[Address] + error: Optional[Exception] + + +def process_message_call( + message: Message, env: Environment +) -> MessageCallOutput: + """ + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + """ + if message.target == Bytes0(b""): + is_collision = account_has_code_or_nonce( + env.state, message.current_target + ) + if is_collision: + return MessageCallOutput( + Uint(0), U256(0), tuple(), set(), AddressCollision() + ) + else: + evm = process_create_message(message, env) + else: + evm = process_message(message, env) + + if evm.error: + logs: Tuple[Log, ...] = () + accounts_to_delete = set() + refund_counter = U256(0) + else: + logs = evm.logs + accounts_to_delete = evm.accounts_to_delete + refund_counter = evm.refund_counter + + tx_end = TransactionEnd(message.gas - evm.gas_left, evm.output, evm.error) + evm_trace(evm, tx_end) + + return MessageCallOutput( + gas_left=evm.gas_left, + refund_counter=refund_counter, + logs=logs, + accounts_to_delete=accounts_to_delete, + error=evm.error, + ) + + +def process_create_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.tangerine_whistle.vm.Evm` + Items containing execution specific objects. + """ + # take snapshot of state before processing the message + begin_transaction(env.state) + + # If the address where the account is being created has storage, it is + # destroyed. This can only happen in the following highly unlikely + # circumstances: + # * The address created by two `CREATE` calls collide. + # * The first `CREATE` left empty code. + destroy_storage(env.state, message.current_target) + + evm = process_message(message, env) + if not evm.error: + contract_code = evm.output + contract_code_gas = len(contract_code) * GAS_CODE_DEPOSIT + try: + charge_gas(evm, contract_code_gas) + except ExceptionalHalt as error: + rollback_transaction(env.state) + evm.gas_left = Uint(0) + evm.error = error + else: + set_code(env.state, message.current_target, contract_code) + commit_transaction(env.state) + else: + rollback_transaction(env.state) + return evm + + +def process_message(message: Message, env: Environment) -> Evm: + """ + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.tangerine_whistle.vm.Evm` + Items containing execution specific objects + """ + if message.depth > STACK_DEPTH_LIMIT: + raise StackDepthLimitError("Stack depth limit reached") + + # take snapshot of state before processing the message + begin_transaction(env.state) + + touch_account(env.state, message.current_target) + + if message.should_transfer_value and message.value != 0: + move_ether( + env.state, message.caller, message.current_target, message.value + ) + + evm = execute_code(message, env) + if evm.error: + # revert state to the last saved checkpoint + # since the message call resulted in an error + rollback_transaction(env.state) + else: + commit_transaction(env.state) + return evm + + +def execute_code(message: Message, env: Environment) -> Evm: + """ + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + """ + code = message.code + valid_jump_destinations = get_valid_jump_destinations(code) + + evm = Evm( + pc=Uint(0), + stack=[], + memory=bytearray(), + code=code, + gas_left=message.gas, + env=env, + valid_jump_destinations=valid_jump_destinations, + logs=(), + refund_counter=U256(0), + running=True, + message=message, + output=b"", + accounts_to_delete=set(), + error=None, + ) + try: + if evm.message.code_address in PRE_COMPILED_CONTRACTS: + evm_trace(evm, PrecompileStart(evm.message.code_address)) + PRE_COMPILED_CONTRACTS[evm.message.code_address](evm) + evm_trace(evm, PrecompileEnd()) + return evm + + while evm.running and evm.pc < len(evm.code): + try: + op = Ops(evm.code[evm.pc]) + except ValueError: + raise InvalidOpcode(evm.code[evm.pc]) + + evm_trace(evm, OpStart(op)) + op_implementation[op](evm) + evm_trace(evm, OpEnd()) + + evm_trace(evm, EvmStop(Ops.STOP)) + + except ExceptionalHalt as error: + evm_trace(evm, OpException(error)) + evm.gas_left = Uint(0) + evm.error = error + return evm +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/memory.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/memory.md new file mode 100644 index 00000000..39deaf59 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/memory.md @@ -0,0 +1,86 @@ +# ๐Ÿ memory.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/memory.py) + +```python +""" +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +""" +from ethereum.utils.byte import right_pad_zero_bytes + +from ...base_types import U256, Bytes, Uint + + +def memory_write( + memory: bytearray, start_position: U256, value: Bytes +) -> None: + """ + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + """ + memory[start_position : Uint(start_position) + len(value)] = value + + +def memory_read_bytes( + memory: bytearray, start_position: U256, size: U256 +) -> bytearray: + """ + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return memory[start_position : Uint(start_position) + Uint(size)] + + +def buffer_read(buffer: Bytes, start_position: U256, size: U256) -> Bytes: + """ + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + """ + return right_pad_zero_bytes( + buffer[start_position : Uint(start_position) + Uint(size)], size + ) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/__init__.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/__init__.md new file mode 100644 index 00000000..9c9a9a20 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/__init__.md @@ -0,0 +1,34 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +""" + +from ...utils.hexadecimal import hex_to_address + +__all__ = ( + "ECRECOVER_ADDRESS", + "SHA256_ADDRESS", + "RIPEMD160_ADDRESS", + "IDENTITY_ADDRESS", +) + +ECRECOVER_ADDRESS = hex_to_address("0x01") +SHA256_ADDRESS = hex_to_address("0x02") +RIPEMD160_ADDRESS = hex_to_address("0x03") +IDENTITY_ADDRESS = hex_to_address("0x04") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/ecrecover.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/ecrecover.md new file mode 100644 index 00000000..7d1eb065 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/ecrecover.md @@ -0,0 +1,67 @@ +# ๐Ÿ ecrecover.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.py) + +```python +""" +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +""" +from ethereum.base_types import U256 +from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.byte import left_pad_zero_bytes + +from ...vm import Evm +from ...vm.gas import GAS_ECRECOVER, charge_gas +from ...vm.memory import buffer_read + + +def ecrecover(evm: Evm) -> None: + """ + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + charge_gas(evm, GAS_ECRECOVER) + + # OPERATION + message_hash_bytes = buffer_read(data, U256(0), U256(32)) + message_hash = Hash32(message_hash_bytes) + v = U256.from_be_bytes(buffer_read(data, U256(32), U256(32))) + r = U256.from_be_bytes(buffer_read(data, U256(64), U256(32))) + s = U256.from_be_bytes(buffer_read(data, U256(96), U256(32))) + + if v != 27 and v != 28: + return + if 0 >= r or r >= SECP256K1N: + return + if 0 >= s or s >= SECP256K1N: + return + + try: + public_key = secp256k1_recover(r, s, v - 27, message_hash) + except ValueError: + # unable to extract public key + return + + address = keccak256(public_key)[12:32] + padded_address = left_pad_zero_bytes(address, 32) + evm.output = padded_address +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/identity.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/identity.md new file mode 100644 index 00000000..48f40fa0 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/identity.md @@ -0,0 +1,43 @@ +# ๐Ÿ identity.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.py) + +```python +""" +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +""" +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_IDENTITY, GAS_IDENTITY_WORD, charge_gas + + +def identity(evm: Evm) -> None: + """ + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_IDENTITY + GAS_IDENTITY_WORD * word_count) + + # OPERATION + evm.output = data +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/mapping.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/mapping.md new file mode 100644 index 00000000..bc2b7336 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/mapping.md @@ -0,0 +1,39 @@ +# ๐Ÿ mapping.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.py) + +```python +""" +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +""" +from typing import Callable, Dict + +from ...fork_types import Address +from . import ( + ECRECOVER_ADDRESS, + IDENTITY_ADDRESS, + RIPEMD160_ADDRESS, + SHA256_ADDRESS, +) +from .ecrecover import ecrecover +from .identity import identity +from .ripemd160 import ripemd160 +from .sha256 import sha256 + +PRE_COMPILED_CONTRACTS: Dict[Address, Callable] = { + ECRECOVER_ADDRESS: ecrecover, + SHA256_ADDRESS: sha256, + RIPEMD160_ADDRESS: ripemd160, + IDENTITY_ADDRESS: identity, +} +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/ripemd160.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/ripemd160.md new file mode 100644 index 00000000..ef46f78b --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/ripemd160.md @@ -0,0 +1,48 @@ +# ๐Ÿ ripemd160.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.py) + +```python +""" +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.byte import left_pad_zero_bytes +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_RIPEMD160, GAS_RIPEMD160_WORD, charge_gas + + +def ripemd160(evm: Evm) -> None: + """ + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_RIPEMD160 + GAS_RIPEMD160_WORD * word_count) + + # OPERATION + hash_bytes = hashlib.new("ripemd160", data).digest() + padded_hash = left_pad_zero_bytes(hash_bytes, 32) + evm.output = padded_hash +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/sha256.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/sha256.md new file mode 100644 index 00000000..ba70383e --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/precompiled_contracts/sha256.md @@ -0,0 +1,45 @@ +# ๐Ÿ sha256.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.py) + +```python +""" +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +""" +import hashlib + +from ethereum.base_types import Uint +from ethereum.utils.numeric import ceil32 + +from ...vm import Evm +from ...vm.gas import GAS_SHA256, GAS_SHA256_WORD, charge_gas + + +def sha256(evm: Evm) -> None: + """ + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + """ + data = evm.message.data + + # GAS + word_count = ceil32(Uint(len(data))) // 32 + charge_gas(evm, GAS_SHA256 + GAS_SHA256_WORD * word_count) + + # OPERATION + evm.output = hashlib.sha256(data).digest() +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/runtime.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/runtime.md new file mode 100644 index 00000000..5a355b19 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/runtime.md @@ -0,0 +1,73 @@ +# ๐Ÿ runtime.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/runtime.py) + +```python +""" +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +""" +from typing import Set + +from ethereum.base_types import Uint + +from .instructions import Ops + + +def get_valid_jump_destinations(code: bytes) -> Set[Uint]: + """ + 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. + """ + valid_jump_destinations = set() + pc = Uint(0) + + while pc < len(code): + try: + current_opcode = Ops(code[pc]) + except ValueError: + # Skip invalid opcodes, as they don't affect the jumpdest + # analysis. Nevertheless, such invalid opcodes would be caught + # and raised when the interpreter runs. + pc += 1 + continue + + if current_opcode == Ops.JUMPDEST: + valid_jump_destinations.add(pc) + elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: + # If PUSH-N opcodes are encountered, skip the current opcode along + # with the trailing data segment corresponding to the PUSH-N + # opcodes. + push_data_size = current_opcode.value - Ops.PUSH1.value + 1 + pc += push_data_size + + pc += 1 + + return valid_jump_destinations +``` diff --git a/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/stack.md b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/stack.md new file mode 100644 index 00000000..9bd5de9c --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/tangerine_whistle/vm/stack.md @@ -0,0 +1,65 @@ +# ๐Ÿ stack.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/tangerine_whistle/vm/stack.py) + +```python +""" +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +""" + +from typing import List + +from ethereum.base_types import U256 + +from .exceptions import StackOverflowError, StackUnderflowError + + +def pop(stack: List[U256]) -> U256: + """ + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + """ + if len(stack) == 0: + raise StackUnderflowError + + return stack.pop() + + +def push(stack: List[U256], value: U256) -> None: + """ + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + """ + if len(stack) == 1024: + raise StackOverflowError + + return stack.append(value) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/trace.md b/docs/revm-python-spec/revm-verif/spec/trace.md new file mode 100644 index 00000000..920b2fb8 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/trace.md @@ -0,0 +1,116 @@ +# ๐Ÿ trace.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/./trace.py) + +```python +""" +.. _trace: + +EVM Trace +^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Defines the functions required for creating evm traces during execution. +""" + +import enum +from dataclasses import dataclass +from typing import Optional, Union + + +@dataclass +class TransactionStart: + """Trace event that is triggered at the start of a transaction.""" + + pass + + +@dataclass +class TransactionEnd: + """Trace event that is triggered at the end of a transaction.""" + + gas_used: int + output: bytes + error: Optional[Exception] + + +@dataclass +class PrecompileStart: + """Trace event that is triggered before executing a precompile.""" + + address: bytes + + +@dataclass +class PrecompileEnd: + """Trace event that is triggered after executing a precompile.""" + + pass + + +@dataclass +class OpStart: + """Trace event that is triggered before executing an opcode.""" + + op: enum.Enum + + +@dataclass +class OpEnd: + """Trace event that is triggered after executing an opcode.""" + + pass + + +@dataclass +class OpException: + """Trace event that is triggered when an opcode raises an exception.""" + + error: Exception + + +@dataclass +class EvmStop: + """Trace event that is triggered when the EVM stops.""" + + op: enum.Enum + + +@dataclass +class GasAndRefund: + """Trace event that is triggered when gas is deducted.""" + + gas_cost: int + + +TraceEvent = Union[ + TransactionStart, + TransactionEnd, + PrecompileStart, + PrecompileEnd, + OpStart, + OpEnd, + OpException, + EvmStop, + GasAndRefund, +] + + +def evm_trace( + evm: object, + event: TraceEvent, + trace_memory: bool = False, + trace_stack: bool = True, + trace_return_data: bool = False, +) -> None: + """ + Create a trace of the event. + """ + pass +``` diff --git a/docs/revm-python-spec/revm-verif/spec/utils/__init__.md b/docs/revm-python-spec/revm-verif/spec/utils/__init__.md new file mode 100644 index 00000000..033e23b3 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/utils/__init__.md @@ -0,0 +1,9 @@ +# ๐Ÿ __init__.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/utils/__init__.py) + +```python +""" +Utility functions used in this specification. +""" +``` diff --git a/docs/revm-python-spec/revm-verif/spec/utils/byte.md b/docs/revm-python-spec/revm-verif/spec/utils/byte.md new file mode 100644 index 00000000..2c3bfcaf --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/utils/byte.md @@ -0,0 +1,58 @@ +# ๐Ÿ byte.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/utils/byte.py) + +```python +""" +Utility Functions For Byte Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Byte specific utility functions used in this specification. +""" +from ethereum.base_types import Bytes + + +def left_pad_zero_bytes(value: Bytes, size: int) -> Bytes: + """ + Left pad zeroes to `value` if it's 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`. + """ + return value.rjust(size, b"\x00") + + +def right_pad_zero_bytes(value: Bytes, size: int) -> Bytes: + """ + Right pad zeroes to `value` if it's 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`. + """ + return value.ljust(size, b"\x00") +``` diff --git a/docs/revm-python-spec/revm-verif/spec/utils/ensure.md b/docs/revm-python-spec/revm-verif/spec/utils/ensure.md new file mode 100644 index 00000000..d9a47db9 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/utils/ensure.md @@ -0,0 +1,42 @@ +# ๐Ÿ ensure.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/utils/ensure.py) + +```python +""" +Ensure (Assertion) Utilities +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Functions that simplify checking assertions and raising exceptions. +""" + +from typing import Type, Union + + +def ensure( + value: bool, exception: Union[Type[BaseException], BaseException] +) -> None: + """ + Does nothing if `value` is truthy, otherwise raises the exception returned + by `exception_class`. + + Parameters + ---------- + + value : + Value that should be true. + + exception : + Constructor for the exception to raise. + """ + if value: + return + raise exception +``` diff --git a/docs/revm-python-spec/revm-verif/spec/utils/hexadecimal.md b/docs/revm-python-spec/revm-verif/spec/utils/hexadecimal.md new file mode 100644 index 00000000..51d3f688 --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/utils/hexadecimal.md @@ -0,0 +1,223 @@ +# ๐Ÿ hexadecimal.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/utils/hexadecimal.py) + +```python +""" +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal strings specific utility functions used in this specification. +""" +from ethereum.base_types import ( + U64, + U256, + Bytes, + Bytes8, + Bytes20, + Bytes32, + Bytes256, + Uint, +) +from ethereum.crypto.hash import Hash32 + + +def has_hex_prefix(hex_string: str) -> bool: + """ + Check if a hex string starts with hex prefix (0x). + + Parameters + ---------- + hex_string : + The hexadecimal string to be checked for presence of prefix. + + Returns + ------- + has_prefix : `bool` + Boolean indicating whether the hex string has 0x prefix. + """ + return hex_string.startswith("0x") + + +def remove_hex_prefix(hex_string: str) -> str: + """ + Remove 0x prefix from a hex string if present. This function returns the + passed hex string if it isn't prefixed with 0x. + + Parameters + ---------- + hex_string : + The hexadecimal string whose prefix is to be removed. + + Returns + ------- + modified_hex_string : `str` + The hexadecimal string with the 0x prefix removed if present. + """ + if has_hex_prefix(hex_string): + return hex_string[len("0x") :] + + return hex_string + + +def hex_to_bytes(hex_string: str) -> Bytes: + """ + Convert hex string to bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bytes. + + Returns + ------- + byte_stream : `bytes` + Byte stream corresponding to the given hexadecimal string. + """ + return bytes.fromhex(remove_hex_prefix(hex_string)) + + +def hex_to_bytes8(hex_string: str) -> Bytes8: + """ + Convert hex string to 8 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 8 bytes. + + Returns + ------- + 8_byte_stream : `Bytes8` + 8-byte stream corresponding to the given hexadecimal string. + """ + return Bytes8(bytes.fromhex(remove_hex_prefix(hex_string).rjust(16, "0"))) + + +def hex_to_bytes20(hex_string: str) -> Bytes20: + """ + Convert hex string to 20 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 20 bytes. + + Returns + ------- + 20_byte_stream : `Bytes20` + 20-byte stream corresponding to the given hexadecimal string. + """ + return Bytes20(bytes.fromhex(remove_hex_prefix(hex_string).rjust(20, "0"))) + + +def hex_to_bytes32(hex_string: str) -> Bytes32: + """ + Convert hex string to 32 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 32 bytes. + + Returns + ------- + 32_byte_stream : `Bytes32` + 32-byte stream corresponding to the given hexadecimal string. + """ + return Bytes32(bytes.fromhex(remove_hex_prefix(hex_string).rjust(64, "0"))) + + +def hex_to_bytes256(hex_string: str) -> Bytes256: + """ + Convert hex string to 256 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 256 bytes. + + Returns + ------- + 256_byte_stream : `Bytes256` + 256-byte stream corresponding to the given hexadecimal string. + """ + return Bytes256( + bytes.fromhex(remove_hex_prefix(hex_string).rjust(512, "0")) + ) + + +def hex_to_hash(hex_string: str) -> Hash32: + """ + Convert hex string to hash32 (32 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to hash32. + + Returns + ------- + hash : `Hash32` + 32-byte stream obtained from the given hexadecimal string. + """ + return Hash32(bytes.fromhex(remove_hex_prefix(hex_string))) + + +def hex_to_uint(hex_string: str) -> Uint: + """ + Convert hex string to Uint. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Uint. + + Returns + ------- + converted : `Uint` + The unsigned integer obtained from the given hexadecimal string. + """ + return Uint(int(remove_hex_prefix(hex_string), 16)) + + +def hex_to_u64(hex_string: str) -> U64: + """ + Convert hex string to U64. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to U256. + + Returns + ------- + converted : `U64` + The U64 integer obtained from the given hexadecimal string. + """ + return U64(int(remove_hex_prefix(hex_string), 16)) + + +def hex_to_u256(hex_string: str) -> U256: + """ + Convert hex string to U256. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to U256. + + Returns + ------- + converted : `U256` + The U256 integer obtained from the given hexadecimal string. + """ + return U256(int(remove_hex_prefix(hex_string), 16)) +``` diff --git a/docs/revm-python-spec/revm-verif/spec/utils/numeric.md b/docs/revm-python-spec/revm-verif/spec/utils/numeric.md new file mode 100644 index 00000000..d0931a3a --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/utils/numeric.md @@ -0,0 +1,207 @@ +# ๐Ÿ numeric.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/utils/numeric.py) + +```python +""" +Utility Functions For Numeric Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Numeric operations specific utility functions used in this specification. +""" +from typing import Sequence, Tuple + +from ethereum.base_types import U32, Uint + + +def get_sign(value: int) -> int: + """ + Determines the sign of a number. + + Parameters + ---------- + value : + The value whose sign is to be determined. + + Returns + ------- + sign : `int` + The sign of the number (-1 or 0 or 1). + The return value is based on math signum function. + """ + if value < 0: + return -1 + elif value == 0: + return 0 + else: + return 1 + + +def ceil32(value: Uint) -> Uint: + """ + Converts a unsigned integer to the next closest multiple of 32. + + Parameters + ---------- + value : + The value whose ceil32 is to be calculated. + + Returns + ------- + ceil32 : `ethereum.base_types.U256` + The same value if it's a perfect multiple of 32 + else it returns the smallest multiple of 32 + that is greater than `value`. + """ + ceiling = Uint(32) + remainder = value % ceiling + if remainder == Uint(0): + return value + else: + return value + ceiling - remainder + + +def is_prime(number: int) -> bool: + """ + Checks if `number` is a prime number. + + Parameters + ---------- + number : + The number to check for primality. + + Returns + ------- + is_number_prime : `bool` + Boolean indicating if `number` is prime or not. + """ + if number <= 1: + return False + + # number ** 0.5 is faster than math.sqrt(number) + for x in range(2, int(number**0.5) + 1): + # Return False if number is divisible by x + if number % x == 0: + return False + + return True + + +def le_bytes_to_uint32_sequence(data: bytes) -> Tuple[U32, ...]: + """ + 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. + """ + sequence = [] + for i in range(0, len(data), 4): + sequence.append(U32.from_le_bytes(data[i : i + 4])) + + return tuple(sequence) + + +def le_uint32_sequence_to_bytes(sequence: Sequence[U32]) -> bytes: + r""" + 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. + """ + result_bytes = b"" + for item in sequence: + result_bytes += item.to_le_bytes4() + + return result_bytes + + +def le_uint32_sequence_to_uint(sequence: Sequence[U32]) -> Uint: + """ + Obtain Uint from a U32 sequence assuming that this sequence is little + endian i.e., the first U32 number of the sequence is the least + significant U32 number. + + Parameters + ---------- + sequence : + The U32 stream (little endian) which is to be converted to a Uint. + + Returns + ------- + value : `Uint` + The Uint number obtained from the conversion of the little endian + U32 stream. + """ + sequence_as_bytes = le_uint32_sequence_to_bytes(sequence) + return Uint.from_le_bytes(sequence_as_bytes) + + +def taylor_exponential( + factor: Uint, numerator: Uint, denominator: Uint +) -> Uint: + """ + Approximates factor * e ** (numerator / denominator) using + Taylor expansion. + + Parameters + ---------- + factor : + The factor. + numerator : + The numerator of the exponential. + denominator : + The denominator of the exponential. + + Returns + ------- + output : `ethereum.base_types.Uint` + The approximation of factor * e ** (numerator / denominator). + + """ + i = 1 + output = 0 + numerator_accumulated = factor * denominator + while numerator_accumulated > 0: + output += numerator_accumulated + numerator_accumulated = (numerator_accumulated * numerator) // ( + denominator * i + ) + i += 1 + return output // denominator +``` diff --git a/docs/revm-python-spec/revm-verif/spec/utils/safe_arithmetic.md b/docs/revm-python-spec/revm-verif/spec/utils/safe_arithmetic.md new file mode 100644 index 00000000..4dec32ca --- /dev/null +++ b/docs/revm-python-spec/revm-verif/spec/utils/safe_arithmetic.md @@ -0,0 +1,101 @@ +# ๐Ÿ safe_arithmetic.py + +[๐Ÿ™ GitHub source](https://github.com/ethereum/execution-specs/blob/c5415056a4a7066906f67c203ec5364a9de8e017/src/ethereum/utils/safe_arithmetic.py) + +```python +""" +Safe Arithmetic for U256 Integer Type +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Safe arithmetic utility functions for U256 integer type. +""" +from typing import Optional, Type, Union + +from ethereum.base_types import U256, Uint + + +def u256_safe_add( + *numbers: Union[U256, Uint], + exception_type: Optional[Type[BaseException]] = None +) -> U256: + """ + Adds together the given sequence of numbers. If the total sum of the + numbers exceeds `U256.MAX_VALUE` then an exception is raised. + If `exception_type` = None then the exception raised defaults to the one + raised by `U256` when `U256.value > U256.MAX_VALUE` + else `exception_type` is raised. + + Parameters + ---------- + numbers : + The sequence of numbers that need to be added together. + + exception_type: + The exception that needs to be raised if the sum of the `numbers` + exceeds `U256.MAX_VALUE`. + + Returns + ------- + result : `ethereum.base_types.U256` + The sum of the given sequence of numbers if the total is less than + `U256.MAX_VALUE` else an exception is raised. + If `exception_type` = None then the exception raised defaults to the + one raised by `U256` when `U256.value > U256.MAX_VALUE` + else `exception_type` is raised. + """ + try: + return U256(sum(numbers)) + except ValueError as e: + if exception_type: + raise exception_type from e + else: + raise e + + +def u256_safe_multiply( + *numbers: Union[U256, Uint], + exception_type: Optional[Type[BaseException]] = None +) -> U256: + """ + Multiplies together the given sequence of numbers. If the net product of + the numbers exceeds `U256.MAX_VALUE` then an exception is raised. + If `exception_type` = None then the exception raised defaults to the one + raised by `U256` when `U256.value > U256.MAX_VALUE` else + `exception_type` is raised. + + Parameters + ---------- + numbers : + The sequence of numbers that need to be multiplies together. + + exception_type: + The exception that needs to be raised if the sum of the `numbers` + exceeds `U256.MAX_VALUE`. + + Returns + ------- + result : `ethereum.base_types.U256` + The multiplication product of the given sequence of numbers if the + net product is less than `U256.MAX_VALUE` else an exception is raised. + If `exception_type` = None then the exception raised defaults to the + one raised by `U256` when `U256.value > U256.MAX_VALUE` + else `exception_type` is raised. + """ + result = numbers[0] + try: + for number in numbers[1:]: + result *= number + return U256(result) + except ValueError as e: + if exception_type: + raise exception_type from e + else: + raise e +``` diff --git a/docusaurus.config.js b/docusaurus.config.js index fe801115..e240f26a 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -232,7 +232,7 @@ const config = { ], // copyright: `Copyright ยฉ ${new Date().getFullYear()} Formal Land (Arae SARL) ๐Ÿฆ, Paris
Formal verification for everyday-life programs ๐Ÿ‡${liveChat}`, // copyright: `Copyright ยฉ ${new Date().getFullYear()} Formal Land (Arae SARL) ๐Ÿฆ, Paris
Prevent all bugs ๐Ÿ‡${liveChat}`, - copyright: `Copyright ยฉ ${new Date().getFullYear()} Formal Land (Arae SARL) ๐Ÿฆ, Paris
Formal verification for everyday-life applications ๐Ÿ‡${liveChat}`, + copyright: `Copyright ยฉ ${new Date().getFullYear()} Formal Land (Arae SARL) ๐Ÿฆ, Paris
Formal verification for everyday-life applications${liveChat}`, }, colorMode: { defaultMode: 'light', diff --git a/sidebars.js b/sidebars.js index 8e9b2247..c5e3e1f1 100644 --- a/sidebars.js +++ b/sidebars.js @@ -89,5 +89,9 @@ module.exports = { }, ], }, + { + type: 'autogenerated', + dirName: 'revm-python-spec', + }, ], }; From 0d61b14d2bf8b3a6711ec595bc5c1e62cccbd9ab Mon Sep 17 00:00:00 2001 From: Guillaume Claret Date: Mon, 17 Jun 2024 18:14:21 +0200 Subject: [PATCH 2/2] wip --- docs/revm-python-spec/revm-verif/revm-verif.md | 2 +- docusaurus.config.js | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/revm-python-spec/revm-verif/revm-verif.md b/docs/revm-python-spec/revm-verif/revm-verif.md index 278f0c79..9f510f01 100644 --- a/docs/revm-python-spec/revm-verif/revm-verif.md +++ b/docs/revm-python-spec/revm-verif/revm-verif.md @@ -1,6 +1,6 @@ # Revm Verification -The goal of this project is to formally verify the [Rust implementation of the EVM](https://github.com/bluealloy/revm) by showing that it is equivalent to the [Python specification of the EVM](https://github.com/ethereum/execution-specs). +The goal of this project is to formally verify the [Rust implementation of the EVM](https://github.com/bluealloy/revm) by showing that it is equivalent to the [Python specification of the EVM](https://github.com/ethereum/execution-specs). The [EVM](https://ethereum.org/en/developers/docs/evm/) is the virtual machine of the Ethereum blockchain to execute smart contracts. We use the [Coq](https://coq.inria.fr/) proof assistant to do the proofs. We use [coq-of-rust](https://github.com/formal-land/coq-of-rust) to convert the Rust code to Coq, and [coq-of-python](https://github.com/formal-land/coq-of-python) to convert the Python code to Coq. diff --git a/docusaurus.config.js b/docusaurus.config.js index e240f26a..b434d4fc 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -137,7 +137,16 @@ const config = { position: 'left', label: 'coq-of-ocaml', }, - {to: '/blog', label: 'Blog', position: 'left'}, + { + to: 'docs/revm-python-spec/revm-verif', + position: 'left', + label: 'Revm', + }, + { + to: '/blog', + label: 'Blog', + position: 'left', + }, { href: 'https://github.com/formal-land', label: 'GitHub',